WebRTC: Renegotiation in firefox

2020-01-29 10:56发布

According to this article, re-negotiation is implemented in firefox v38 and we can add remove streams from same peerconnections without creating new ones, but I am unable to find any working demos to support that claim, and when I tried it, two users chating in video mode, I changing one of their stream to audio, I get the error:

NotSupportedError: removeStream not yet implemented

this tells the same, but this tells renegotiation events are supported, but isn't removeStream key part of renegotiation? I am using firefox version 39 in windows 7. I am confused, renegotiation is not yet supported in firefox, right?

2条回答
放荡不羁爱自由
2楼-- · 2020-01-29 11:32

Renegotiation is supported in Firefox.

Firefox just never implemented removeStream because the spec had changed to addTrack and removeTrack by the time renegotiation was implemented (some are suggesting that its removal was too hasty, so it may come back). addStream still works for backwards compatibility, because Firefox already supported it.

Note that removeTrack confusingly takes the RTCRtpSender returned from addTrack so the API is not a drop-in.

A polyfill would look something like this:

mozRTCPeerConnection.prototype.removeStream = function(stream) {
  this.getSenders().forEach(sender =>
      stream.getTracks().includes(sender.track) && this.removeTrack(sender));
}

The move to tracks was done to give users more flexibility, since tracks may belong to multiple streams, and not all tracks in a stream need be sent over a PeerConnection (or the same PeerConnection).

See this answer to a different question for a renegotiation example that works in Firefox.

查看更多
该账号已被封号
3楼-- · 2020-01-29 11:35

Try using replaceTrack for individual tracks, instead of replacing the entire stream. This example assumes you have a peer connection pc1 and a new stream newStream to replace on it. Get the senders, and replace the tracks with appropriate tracks from the new stream. Working sample here.

Promise.all(pc1.getSenders().map(sender =>
  sender.replaceTrack((sender.track.kind == "audio")?
                      newStream.getAudioTracks()[0] :
                      newStream.getVideoTracks()[0])))
.then(() => log("Flip!"))
.catch(failed);

Also note this, from your first link:

function screenShare() {
    let screenConstraints = {video: {mediaSource: "screen"}};

    navigator.mediaDevices.getUserMedia(screenConstraints)
    .then(stream) {
        stream.getTracks().forEach(track) {
            screenStream = stream;
            screenSenders.push(pc1.addTrack(track, stream));
        });
    });
}

Notice that this example calls pc1.addTrack not pc1.addStream

And in the same in reverse, for removing - pc1.removeTrack:

function stopScreenShare() {
    screenStream.stop();
    screenSenders.forEach(sender) {
        pc1.removeTrack(sender);
    });
}
查看更多
登录 后发表回答