I am trying to implement, the video on/off toggle for a webRtc application in react, so far i am able to stop the video using
userStream.getVideoTracks()[0].stop()
but can't seem to find any function to restart the video track .
I have tried the .enable method
userStream.getVideoTracks()[0].enabled = !userStream.getVideoTracks()[0]
but using this still leaves the webcam light on, which in undesirable but gets the functionality working,
on the other hand userStream.getVideoTracks()[0].stop() turns off the light but i am not able start it back.
Is there anyway to achive this without creating a new stream.
When you use track.stop() you can't reuse the track. You'll have to create a new one.
With the track.enabled method it should normally get the functionality that you're looking for. Disabling the camera indicator when disabled. Because as the official docs state:
If the MediaStreamTrack represents the video input from a camera, disabling the track by setting enabled to false also updates device activity indicators to show that the camera is not currently recording or streaming. For example, the green "in use" light next to the camera in iMac and MacBook computers turns off while the track is muted in this way.
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/enabled
It could be another track is still using your track or it could be something browser version related why your camera indicator is still on.
best way to do is you can replace tracks.
function replaceTracks(elementId, newStream, localStream, peerConnection) {
detachMediaStream(elementId);
newStream.getTracks().forEach(function (track) {
localStream.addTrack(track);
});
attachMediaStream(elementId, newStream);
// optionally, if you have active peer connections:
_replaceTracksForPeer(peerConnection);
function _replaceTracksForPeer(peer) {
console.log(peer)
peer.getSenders().map(function (sender) {
sender.replaceTrack(newStream.getTracks().find(function (track) {
return track.kind === sender.track.kind;
}));
});
}
function attachMediaStream(id, stream) {
var elem: any = document.getElementById(id);
if (elem) {
if (typeof elem.srcObject === 'object') {
elem.srcObject = stream;
} else {
elem.src = window.URL.createObjectURL(stream);
}
elem.onloadedmetadata = function (e) {
elem.play();
};
} else {
throw new Error('Unable to attach media stream');
}
}
function detachMediaStream(id) {
var elem;
elem = document.getElementById(id);
if (elem) {
elem.pause();
if (typeof elem.srcObject === 'object') {
elem.srcObject = null;
} else {
elem.src = '';
}
}
}
}
I opened a webcam by using the following JavaScript code:
const stream = await navigator.mediaDevices.getUserMedia({ /* ... */ });
Is there any JavaScript code to stop or close the webcam?
Since this answer has been originally posted the browser API has changed.
.stop() is no longer available on the stream that gets passed to the callback.
The developer will have to access the tracks that make up the stream (audio or video) and stop each of them individually.
More info here: https://developers.google.com/web/updates/2015/07/mediastream-deprecations?hl=en#stop-ended-and-active
Example (from the link above):
stream.getTracks().forEach(function(track) {
track.stop();
});
Browser support may differ.
Previously, navigator.getUserMedia provided you with a stream in the success callback, you could call .stop() on that stream to stop the recording (at least in Chrome, seems FF doesn't like it)
Use any of these functions:
// stop both mic and camera
function stopBothVideoAndAudio(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live') {
track.stop();
}
});
}
// stop only camera
function stopVideoOnly(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live' && track.kind === 'video') {
track.stop();
}
});
}
// stop only mic
function stopAudioOnly(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live' && track.kind === 'audio') {
track.stop();
}
});
}
Don't use stream.stop(), it's deprecated
MediaStream Deprecations
Use stream.getTracks().forEach(track => track.stop())
FF, Chrome and Opera has started exposing getUserMedia via navigator.mediaDevices as standard now (Might change :)
online demo
navigator.mediaDevices.getUserMedia({audio:true,video:true})
.then(stream => {
window.localStream = stream;
})
.catch( (err) =>{
console.log(err);
});
// later you can do below
// stop both video and audio
localStream.getTracks().forEach( (track) => {
track.stop();
});
// stop only audio
localStream.getAudioTracks()[0].stop();
// stop only video
localStream.getVideoTracks()[0].stop();
Suppose we have streaming in video tag and id is video - <video id="video"></video> then we should have following code -
var videoEl = document.getElementById('video');
// now get the steam
stream = videoEl.srcObject;
// now get all tracks
tracks = stream.getTracks();
// now close each track by having forEach loop
tracks.forEach(function(track) {
// stopping every track
track.stop();
});
// assign null to srcObject of video
videoEl.srcObject = null;
Starting Webcam Video with different browsers
For Opera 12
window.navigator.getUserMedia(param, function(stream) {
video.src =window.URL.createObjectURL(stream);
}, videoError );
For Firefox Nightly 18.0
window.navigator.mozGetUserMedia(param, function(stream) {
video.mozSrcObject = stream;
}, videoError );
For Chrome 22
window.navigator.webkitGetUserMedia(param, function(stream) {
video.src =window.webkitURL.createObjectURL(stream);
}, videoError );
Stopping Webcam Video with different browsers
For Opera 12
video.pause();
video.src=null;
For Firefox Nightly 18.0
video.pause();
video.mozSrcObject=null;
For Chrome 22
video.pause();
video.src="";
With this the Webcam light go down everytime...
Try method below:
var mediaStream = null;
navigator.getUserMedia(
{
audio: true,
video: true
},
function (stream) {
mediaStream = stream;
mediaStream.stop = function () {
this.getAudioTracks().forEach(function (track) {
track.stop();
});
this.getVideoTracks().forEach(function (track) { //in case... :)
track.stop();
});
};
/*
* Rest of your code.....
* */
});
/*
* somewhere insdie your code you call
* */
mediaStream.stop();
You can end the stream directly using the stream object returned in the success handler to getUserMedia. e.g.
localMediaStream.stop()
video.src="" or null would just remove the source from video tag. It wont release the hardware.
Since you need the tracks to close the streaming, and you need the stream boject to get to the tracks, the code I have used with the help of the Muaz Khan's answer above is as follows:
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints, function (stream) {
videoEl.src = stream;
videoEl.play();
document.getElementById('close').addEventListener('click', function () {
stopStream(stream);
});
}, errBack);
function stopStream(stream) {
console.log('stop called');
stream.getVideoTracks().forEach(function (track) {
track.stop();
});
Of course this will close all the active video tracks. If you have multiple, you should select accordingly.
If the .stop() is deprecated then I don't think we should re-add it like #MuazKhan dose. It's a reason as to why things get deprecated and should not be used anymore. Just create a helper function instead... Here is a more es6 version
function stopStream (stream) {
for (let track of stream.getTracks()) {
track.stop()
}
}
You need to stop all tracks (from webcam, microphone):
localStream.getTracks().forEach(track => track.stop());
Start and Stop Web Camera,(Update 2020 React es6 )
Start Web Camera
stopWebCamera =()=>
//Start Web Came
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
//use WebCam
navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
this.localStream = stream;
this.video.srcObject = stream;
this.video.play();
});
}
}
Stop Web Camera or Video playback in general
stopVideo =()=>
{
this.video.pause();
this.video.src = "";
this.video.srcObject = null;
// As per new API stop all streams
if (this.localStream)
this.localStream.getTracks().forEach(track => track.stop());
}
Stop Web Camera function works even with video streams:
this.video.src = this.state.videoToTest;
this.video.play();
Using .stop() on the stream works on chrome when connected via http. It does not work when using ssl (https).
Please check this: https://jsfiddle.net/wazb1jks/3/
navigator.getUserMedia(mediaConstraints, function(stream) {
window.streamReference = stream;
}, onMediaError);
Stop Recording
function stopStream() {
if (!window.streamReference) return;
window.streamReference.getAudioTracks().forEach(function(track) {
track.stop();
});
window.streamReference.getVideoTracks().forEach(function(track) {
track.stop();
});
window.streamReference = null;
}
The following code worked for me:
public vidOff() {
let stream = this.video.nativeElement.srcObject;
let tracks = stream.getTracks();
tracks.forEach(function (track) {
track.stop();
});
this.video.nativeElement.srcObject = null;
this.video.nativeElement.stop();
}
Have a reference of stream form successHandle
var streamRef;
var handleVideo = function (stream) {
streamRef = stream;
}
//this will stop video and audio both track
streamRef.getTracks().map(function (val) {
val.stop();
});
I have to create a live streaming video application in which I have to read the video using the external web camera connected to my MacBook. I have to do this using WebRTC. But while executing the code the integrated webcam get triggered instead of the external webcam.
var video = document.querySelector("#videoElement");
var constraints = { audio:true,video: { facingMode:"environment" }
var promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then(function(mediaStream) {
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
How can I trigger the external webcam connected?
https://webrtc.github.io/samples/src/content/devices/input-output/ is the canonical example of how to select devices, demonstrating enumerateDevices() and getUserMedia()
You should take a look at https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API
And this one https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints
if (typeof MediaStreamTrack === 'undefined'){
alert('This browser does not support MediaStreamTrack.\n\nTry Chrome Canary.');
} else {
MediaStreamTrack.getSources( onSourcesAcquired);
}
function onSourcesAcquired(sources) {
for (var i = 0; i != sources.length; ++i) {
var source = sources[i];
// source.id -> DEVICE ID
// source.label -> DEVICE NAME
// source.kind = "audio" OR "video"
// TODO: add this to some datastructure of yours or a selection dialog
}
}
....
constraints = {
audio: {
optional: [{sourceId: selected_audio_source_id}]
},
video: {
optional: [{sourceId: selected_video_source_id}]
}
};
navigator.getUserMedia(constraints, onSuccessCallback, onErrorCallback);
According to facebook documentation - https://developers.facebook.com/docs/plugins/embedded-video-player/api , we subscribe to player events
var handleDesktopEvents = function (msg) {
if (msg.type === 'video') {
var player = msg.instance;
var playHandler = player.subscribe('startedPlaying', function() {
// Video started playing ...
player.unmute();
console.log('detected video playing');
ga_virtual_pagehit(msg.id);
console.log('sent event to GA');
playHandler.removeListener('startedPlaying');
// playHandler.release();
});
console.log('detected video ready');
player.play();
FB.Event.unsubscribe('xfbml.ready', handleDesktopEvents, handleDesktopEx);
}
};
var handleDesktopEx = function () {
// Handle pause() and exceptions
console.log('detected pause');
};
FB.Event.subscribe('xfbml.ready', handleDesktopEvents, handleDesktopEx);
It seems that removeListener() is not available on the token returned by subscribe(). With a debugger, we see that there is a method release() available on the token. Should that be used? Is it now official?
Am I doing something wrong?
there was and probably still is, unless FB changed something again, a release() method. it does what removeListen() should be doing.
I am trying to implement Chrome desktopCapture API with MediaStreamRecorder library. Everything works perfect but the video quality is so blurred and bad. 1 minute desktop captured video takes 14MB.
below is my code:
var pending_request_id;
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
startRecording();
sendResponse({"success": true});
});
function getUserMediaError() {
console.log("getUserMedia() failed.");
}
function onAccessApproved(id) {
if (!id) {
console.log("Access rejected.");
return;
}
navigator.webkitGetUserMedia({
audio:false,
video: { mandatory: { chromeMediaSource: "desktop",
chromeMediaSourceId: id } }
}, onMediaSuccess, getUserMediaError);
}
function startRecording() {
pending_request_id = chrome.desktopCapture.chooseDesktopMedia(
["window"], onAccessApproved);
}
function onMediaSuccess(stream) {
console.log("rcvd stream");
var mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.mimeType = 'video/mp4';
//i dont want strechy video so i fixed the width and height of recorder equal to window
mediaRecorder.width = window.screen.width;
mediaRecorder.height = window.screen.height;
mediaRecorder.ondataavailable = function (blob) {
var blobURL = URL.createObjectURL(blob);
console.log('' + blobURL + '');
var link=blobURL;
var videoInfo="Compiled Video file size: " + Math.ceil(blob.size / 1024) + "KB";
console.log(link);
console.log(videoInfo);
};
mediaRecorder.start(30000); // i want unlimited recording time so i increased the timeslice
stream.onended = function() {
mediaRecorder.stop();
//finalizeVideo();
console.log("Ended"); };
}
function onMediaError(e) {
console.error('media error', e);
}
Before using this library i tried to save streaming video using Whammy.js. but i failed to do so. then i found this library.
Questions :
Is there any way to increase quality of the video and as well as compress video size too?
How to save the video which return as blob:chrome url to desktop as fully qualified video?
As an alternative, If anyone knows how to do this in Whammy.js then kindly let me know
Thanks,
This might help to make your video quality better -
navigator.webkitGetUserMedia({
audio:false,
video: { mandatory: { chromeMediaSource: "desktop",
chromeMediaSourceId: id,
maxWidth: 4000,
maxHeight: 4000 } }
}, onMediaSuccess, getUserMediaError);
}