1

我正在创建多个 webrtc 对等连接并使用创建单个媒体流

if (mediaStream == undefined) {
            navigator.mediaDevices.getUserMedia({
                audio: true,
                video: true
            }).then(function (stream) {
                mediaStream = stream;
                mediaStream.getTracks().forEach(function (track) {
                    rtcPeerConns[userName].addTrack(track, mediaStream);
                });
            }).catch(function (err) {
                console.log("get user media " + err.name + ": " + err.message);
            });
        } else {
            console.log("using the existing local stream");
            mediaStream.getTracks().forEach(function (track) {
                rtcPeerConns[userName].addTrack(track, mediaStream);
            });
        }

一切正常,直到最后一个对等连接关闭并且我想关闭媒体流。

if (mediaStream != undefined) {
        if (mediaStream.active) {
            mediaStream.getTracks().forEach(function (track) {
                track.stop();
            });
            mediaStream = null;
        }
    }

如果只使用了 1 个对等连接,那么一切都会按计划关闭。如果超过 1 个对等连接使用了 MediaStream,则 MediaStream 变为 null ,但浏览器上的摄像头指示灯和摄像头灯都保持亮起。

我错过了什么?

4

1 回答 1

2

That's a bit of a guess, but seems like the most possible reason, so while having more code would help...

If you do enter that first code block

if (mediaStream == undefined) {
    navigator.mediaDevices.getUserMedia({
      ...

again before the first Promise returned by getUserMedia gets resolved, then you will have actually multiple different MediaStreams coming from your device.

The global variable mediaStream will only represent the last MediaStream got from getUserMedia, and all the previous ones while inaccessible from your code, will still lock your device.

Here is an MCVE

In other words, you need to refactor your code.

You need to keep better track of when a request to get the MediaStream has been made, so to make the less changes in your code, I can propose you to actually store the Promise that gets returned by getUserMedia [instead of / along with] storing the MediaStream.

This way, next calls will just have to then() this Promise, in order to access the same MediaStream.

// outer scope
var stream_request = null;
// [...]
function requestStream() {
  if(!stream_request) {
    stream_request =  navigator.mediaDevices.getUserMedia(options);
  }
  return stream_request
       .then(doSomethingWithTheMediaStream);
}

// and to kill it
function kill_stream() {
  return stream_request.then(stream => {
    stream.getTracks().forEach(t => t.stop());
  }
}

live example

于 2018-11-23T04:41:06.410 回答