From 227f1f38557784a9db10886ded364f9815e16534 Mon Sep 17 00:00:00 2001 From: Sangwon Oh Date: Fri, 10 Feb 2023 16:34:39 +0900 Subject: [PATCH] Add stop streaming feature --- README.md | 11 ++-- package.json | 2 +- src/OvenLiveKit.js | 153 ++++++++++++++++++++------------------------- 3 files changed, 76 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index ea2e16a..e9e72be 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ import OvenLiveKit from 'ovenlivekit' This is the simplest example of sending a device media stream such as a webcam to OvenMediaEngine's WebRTC Provider. ```JavaScript // Initialize OvenLiveKit -let ovenLivekit = OvenLiveKit.create(); +const ovenLivekit = OvenLiveKit.create(); // Get media stream from user device ovenLivekit.getUserMedia().then(function () { @@ -104,7 +104,7 @@ var config = { } // Initialize ovenLivekit instance -let ovenLivekit = OvenLiveKit.create(config); +const ovenLivekit = OvenLiveKit.create(config); // Release all resources and destroy the instance ovenLivekit.remove(); @@ -219,7 +219,7 @@ OvenLiveKit also provides APIs to control a media stream from a user device. ``` ```JavaScript // Create instance -let ovenLivekit = OvenLiveKit.create(); +const ovenLivekit = OvenLiveKit.create(); // Attaching video element for playing device stream ovenLivekit.attachMedia(document.getElementById('myVideo')); @@ -254,7 +254,7 @@ ovenLivekit.getUserMedia(constraints).then(function (stream) { Congrats on getting the media stream from the user device and then ready to stream into OvenMediaEngine. ```JavaScript // Create instance -let ovenLivekit = OvenLiveKit.create(); +const ovenLivekit = OvenLiveKit.create(); ovenLivekit.getUserMedia().then(function () { @@ -293,6 +293,9 @@ ovenLivekit.getUserMedia().then(function () { - String: String you want to append to a=fmtp of SDP. - If set video format is appended to the a=fmtp sections of SDP. +#### `instance.stopStreaming()` +- Close peer connection and websocket associated with OvenMediaEngine. + ## For more information * [WebRTC Input in OvenPlayer Demo](https://demo.ovenplayer.com/demo_input.html) * Test Player based on OvenPlayer. diff --git a/package.json b/package.json index e3ed442..003fb64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ovenlivekit", - "version": "1.0.3", + "version": "1.0.4", "description": "OvenLiveKit for Web is an open source JavaScript SDK suite for live streaming from web browsers to OvenMediaEngine.", "main": "dist/OvenLiveKit.min.js", "scripts": { diff --git a/src/OvenLiveKit.js b/src/OvenLiveKit.js index c9562d5..74b83e4 100644 --- a/src/OvenLiveKit.js +++ b/src/OvenLiveKit.js @@ -1,5 +1,6 @@ const OvenLiveKit = {}; +const version = '1.0.4'; const logHeader = 'OvenLiveKit.js :'; const logEventHeader = 'OvenLiveKit.js ===='; @@ -33,15 +34,6 @@ function findIp(string) { return result; } -function checkIOSVersion() { - var agent = window.navigator.userAgent, - start = agent.indexOf('OS '); - if ((agent.indexOf('iPhone') > -1 || agent.indexOf('iPad') > -1) && start > -1) { - return window.Number(agent.substr(start + 3, 3).replace('_', '.')); - } - return 0; -} - function getFormatNumber(sdp, format) { const lines = sdp.split('\r\n'); @@ -143,13 +135,11 @@ function gotDevices(deviceInfos) { function initConfig(instance, options) { - instance.stream = null; + instance.inputStream = null; instance.webSocket = null; instance.peerConnection = null; instance.connectionConfig = {}; - instance.status = 'creating'; - instance.videoElement = null; instance.connectionUrl = null; @@ -159,7 +149,6 @@ function initConfig(instance, options) { } else { instance.callbacks = {}; } - } function addMethod(instance) { @@ -186,14 +175,14 @@ function addMethod(instance) { }; } - console.info(logHeader, 'Requested Constraint To Input Devices', constraints); + console.info(logHeader, 'Request Stream To Input Devices With Constraints', constraints); return navigator.mediaDevices.getUserMedia(constraints) .then(function (stream) { console.info(logHeader, 'Received Media Stream From Input Device', stream); - instance.stream = stream; + instance.inputStream = stream; let elem = instance.videoElement; @@ -230,14 +219,14 @@ function addMethod(instance) { constraints = {}; } - console.info(logHeader, 'Requested Constraint To Display', constraints); + console.info(logHeader, 'Request Stream To Display With Constraints', constraints); return navigator.mediaDevices.getDisplayMedia(constraints) .then(function (stream) { console.info(logHeader, 'Received Media Stream From Display', stream); - instance.stream = stream; + instance.inputStream = stream; let elem = instance.videoElement; @@ -371,10 +360,9 @@ function addMethod(instance) { webSocket.onclose = function (e) { - if (!instance.removing) { + if (!instance.webSocketClosedByUser) { if (instance.callbacks.connectionClosed) { - instance.callbacks.connectionClosed('websocket', e); } } @@ -565,21 +553,12 @@ function addMethod(instance) { instance.peerConnection = peerConnection; // set local stream - instance.stream.getTracks().forEach(function (track) { + instance.inputStream.getTracks().forEach(function (track) { console.info(logHeader, 'Add Track To Peer Connection', track); - peerConnection.addTrack(track, instance.stream); + peerConnection.addTrack(track, instance.inputStream); }); - - if (checkIOSVersion() >= 15) { - const formatNumber = getFormatNumber(offer.sdp, 'H264'); - - if (formatNumber > 0) { - offer.sdp = removeFormat(offer.sdp, formatNumber); - } - } - if (instance.connectionConfig.maxVideoBitrate) { // if bandwith limit is set. modify sdp from ome to limit acceptable bandwidth of ome @@ -599,16 +578,6 @@ function addMethod(instance) { peerConnection.createAnswer() .then(function (answer) { - if (checkIOSVersion() >= 15) { - - const formatNumber = getFormatNumber(answer.sdp, 'H264'); - - if (formatNumber > 0) { - - answer.sdp = removeFormat(answer.sdp, formatNumber); - } - } - if (instance.connectionConfig.sdp && instance.connectionConfig.sdp.appendFmtp) { answer.sdp = appendFmtp(answer.sdp); @@ -651,8 +620,6 @@ function addMethod(instance) { if (e.candidate && e.candidate.candidate) { - console.info(logHeader, 'Candidate Sent', '\n', e.candidate.candidate, '\n', e); - sendMessage(instance.webSocket, { id: id, peer_id: peerId, @@ -675,8 +642,6 @@ function addMethod(instance) { if (state === 'connected') { if (instance.callbacks.connected) { - - console.info(logHeader, 'Iceconnection Connected', e); instance.callbacks.connected(e); } } @@ -684,7 +649,6 @@ function addMethod(instance) { if (state === 'failed' || state === 'disconnected' || state === 'closed') { if (instance.callbacks.connectionClosed) { - console.error(logHeader, 'Iceconnection Closed', e); instance.callbacks.connectionClosed('ice', e); } @@ -713,6 +677,49 @@ function addMethod(instance) { } } + function closePeerConnection() { + if (instance.peerConnection) { + + // remove tracks from peer connection + instance.peerConnection.getSenders().forEach(function (sender) { + instance.peerConnection.removeTrack(sender); + }); + + instance.peerConnection.close(); + instance.peerConnection = null; + delete instance.peerConnection; + } + } + + function closeWebSocket() { + + if (instance.webSocket) { + + instance.webSocket.close(); + instance.webSocket = null; + delete instance.webSocket; + } + } + + function closeInputStream() { + // release video, audio stream + if (instance.inputStream) { + + instance.inputStream.getTracks().forEach(track => { + + track.stop(); + instance.inputStream.removeTrack(track); + }); + + if (instance.videoElement) { + instance.videoElement.srcObject = null; + } + + instance.inputStream = null; + delete instance.inputStream; + } + } + // instance methods instance.attachMedia = function (videoElement) { @@ -741,63 +748,39 @@ function addMethod(instance) { initWebSocket(connectionUrl); }; - instance.remove = function () { - - instance.removing = true; + instance.stopStreaming = function () { - // first release peer connection with ome - if (instance.peerConnection) { + instance.webSocketClosedByUser = true; - // remove tracks from peer connection - instance.peerConnection.getSenders().forEach(function (sender) { - instance.peerConnection.removeTrack(sender); - }); - - instance.peerConnection.close(); - instance.peerConnection = null; - delete instance.peerConnection; - } - - // release video, audio stream - if (instance.stream) { - - instance.stream.getTracks().forEach(track => { - - track.stop(); - instance.stream.removeTrack(track); - }); - - if (instance.videoElement) { - instance.videoElement.srcObject = null; - } - - instance.stream = null; - delete instance.stream; - } + closeWebSocket(); + closePeerConnection(); + }; - // release websocket - if (instance.webSocket) { + instance.remove = function () { - instance.webSocket.close(); - instance.webSocket = null; - delete instance.webSocket; - } + instance.webSocketClosedByUser = true; - instance.status = 'removed'; + closeWebSocket(); + closePeerConnection(); + closeInputStream(); console.info(logEventHeader, 'Removed'); }; } +OvenLiveKit.getVersion = function () { + return version; +} + // static methods OvenLiveKit.create = function (options) { - console.info(logEventHeader, 'Create WebRTC Input v1.0.2'); + console.info(logEventHeader, 'Create WebRTC Input ' + version); let instance = {}; - instance.removing = false; + instance.webSocketClosedByUser = false; initConfig(instance, options); addMethod(instance);