停止/关闭由 navigator.mediaDevices.getUserMedia 打开的网络摄像头流

问题描述 投票:0回答:17

我使用以下 JavaScript 代码打开了网络摄像头:

const stream = await navigator.mediaDevices.getUserMedia({ /* ... */ });

是否有任何 JavaScript 代码可以停止或关闭网络摄像头?

javascript html html5-video webrtc getusermedia
17个回答
344
投票

自从这个答案最初发布以来,浏览器 API 已经发生了变化。

.stop()
在传递给回调的流上不再可用。 开发人员必须访问构成流(音频或视频)的轨道并单独停止每个轨道。

更多信息请参见:https://developers.google.com/web/updates/2015/07/mediastream-deprecations?hl=en#stop-ending-and-active

示例(来自上面的链接):

stream.getTracks().forEach(function(track) {
  track.stop();
});

浏览器支持可能有所不同。

以前,

navigator.getUserMedia
在成功回调中为您提供了一个流,您可以在该流上调用
.stop()
来停止录制(至少在Chrome中,似乎FF不喜欢它)


119
投票

使用以下任意功能:

// stop both mic and camera
function stopBothVideoAndAudio(stream) {
    stream.getTracks().forEach((track) => {
        if (track.readyState == 'live') {
            track.stop();
        }
    });
}

// stop only camera
function stopVideoOnly(stream) {
    stream.getTracks().forEach((track) => {
        if (track.readyState == 'live' && track.kind === 'video') {
            track.stop();
        }
    });
}

// stop only mic
function stopAudioOnly(stream) {
    stream.getTracks().forEach((track) => {
        if (track.readyState == 'live' && track.kind === 'audio') {
            track.stop();
        }
    });
}

62
投票

不要使用

stream.stop()
,它已被弃用

MediaStream 弃用

使用

stream.getTracks().forEach(track => track.stop())


24
投票

FF、Chrome 和 Opera 已开始通过

getUserMedia
公开
navigator.mediaDevices
作为标准(可能会改变:)

在线演示

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();

20
投票

假设我们在视频标签中有流媒体并且 id 是视频 -

<video id="video"></video>
那么我们应该有以下代码 -

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;

10
投票

使用不同的浏览器启动网络摄像头视频

Opera 12

window.navigator.getUserMedia(param, function(stream) {
                            video.src =window.URL.createObjectURL(stream);
                        }, videoError );

适用于 Firefox Nightly 18.0

window.navigator.mozGetUserMedia(param, function(stream) {
                            video.mozSrcObject = stream;
                        }, videoError );

适用于 Chrome 22

window.navigator.webkitGetUserMedia(param, function(stream) {
                            video.src =window.webkitURL.createObjectURL(stream);
                        },  videoError );

使用不同的浏览器停止网络摄像头视频

Opera 12

video.pause();
video.src=null;

适用于 Firefox Nightly 18.0

video.pause();
video.mozSrcObject=null;

适用于 Chrome 22

video.pause();
video.src="";

这样网络摄像头灯每次都会熄灭...


8
投票

尝试以下方法:

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();

6
投票

您可以使用成功处理程序中返回的流对象直接结束流以获取用户媒体。例如

localMediaStream.stop()

video.src=""
null
只会从视频标签中删除源。它不会释放硬件。


4
投票

由于您需要曲目来关闭流媒体,并且需要

stream
对象才能访问曲目,因此我在上面 Muaz Khan 的答案的帮助下使用的代码如下:

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();
});

当然,这将关闭所有活动的视频轨道。如果有多个,则应进行相应选择。


4
投票

如果

.stop()
已被弃用,那么我认为我们不应该像@MuazKhan剂量一样重新添加它。这就是为什么某些东西被弃用并且不应再使用的原因。只需创建一个辅助函数即可...这是一个更 es6 的版本

function stopStream (stream) {
    for (let track of stream.getTracks()) { 
        track.stop()
    }
}

2
投票

您需要停止所有曲目(来自网络摄像头、麦克风):

localStream.getTracks().forEach(track => track.stop());

2
投票

启动和停止网络摄像头,(更新2020 React es6)

启动网络摄像头

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();
        });
      }
 }

一般停止网络摄像头或视频播放

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());
}

即使使用视频流,停止网络摄像头功能也适用:

  this.video.src = this.state.videoToTest;
  this.video.play();

0
投票

通过 http 连接时,在流上使用 .stop() 可在 Chrome 上运行。使用 ssl (https) 时不起作用。


0
投票

请检查:https://jsfiddle.net/wazb1jks/3/

navigator.getUserMedia(mediaConstraints, function(stream) {
    window.streamReference = stream;
}, onMediaError);

停止录音

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;
}


0
投票

以下代码对我有用:

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();
  }

0
投票

我尝试了一切,但只是间歇性地起作用。直到我关闭 React 中的组件后,摄像头灯才消失。我建议在隐藏/显示组件的地方创建组件,以便完全删除相机。


    const stream = document.querySelector("video").srcObject;
    console.log("videoElement", stream, stream.active);

    stream?.getVideoTracks()?.forEach((track) => {
      console.log("track 1", track);
      track.stop();
      stream?.removeTrack(track);
      track = null;
      console.log("track 2", track);
    });
    stream?.getTracks()?.forEach((track) => {
      console.log("track 3", track);
      track.stop();
      stream?.removeTrack(track);
      track = null;
      console.log("track 4", track);
    });
    stream?.getAudioTracks()?.forEach((track) => {
      console.log("track 5", track);
      track.stop();
      stream?.removeTrack(track);
      track = null;
      console.log("track 6", track);
    });
    console.log("videoElement 2", stream, stream.active);
    stream = null;

    const videoElem = document.querySelector("video");
    if (videoElem) {
      console.log("element exists", videoElem);
      videoElem.pause();
      videoElem.removeAttribute("src");
      videoElem.src = "";
      videoElem.remove();
      console.log("element exists 2", videoElem);
    }

因为上面没有完全关闭相机,我建议你拥有你的组件

const [isCameraOn, setCameraOn] = useState(false)

像这样设置你的视频组件

{isCameraOn && (<YourVideoComponent/>)}

-3
投票

有流形式 successHandle 的引用

var streamRef;

var handleVideo = function (stream) {
    streamRef = stream;
}

//this will stop video and audio both track
streamRef.getTracks().map(function (val) {
    val.stop();
});
© www.soinside.com 2019 - 2024. All rights reserved.