首页 > 解决方案 > How to circumvent missing .stop() implementation of RTCRtpTransceiver in Chrome / Chromium

问题描述

I currently try to build a webrtc application that uses the RTCRtpTransceiver-Objects of the WebRTC standard. I add video and audio tracks to the connection and then, some time later, I try to remove them. I do this with the following lines:

// part of a method, that searches the transceiver to stop and assigned it to the 'transceiver' variable
peerconnection.removeTrack(transceiver.sender);
if (transceiver.direction === "sendrecv") transceiver.direction = "recvonly";
else transceiver.direction = "inactive";

I know that this will set the remote track just to muted state and is like replacing the transceivers sender track with null, but Chrome has not implemented direction="stopped" or transceiver.stop() yet, see Issue 980879.
So what to do instead?
The remote peer just sees the current direction of the receiver becoming inactive and the receiver track gets muted.
Ergo, it does not remove the track for the remote peer in my application and muted tracks accumulate over time and even worse for video tracks: they get displayed like normal muted tracks.
I also cannot remove every muted track, since my application is required to allow muted and unmuted tracks (- muted by the user, not muted due to being stopped).
Muting tracks by entirely removing them will lead to another offer-answer exchange and this takes some time. I would prefer to just mute by replacing the track with null (without having to send sdp back and forth), as the WebRTC standard seems to allow and Chrome already implements.
The next option would be correlating the transceivers on both ends and sending a message from the stopping peer to the remote one to make the remote one stop the received track. This may be possible (I believe the transceivers mid should be the same, according to the spec), but in my opinion it is also an ugly way.
What i cannot do is just sending over the media track id, since this one is different for the stopping peer and the remote peer, so I cannot just send a message like 'please stop your track with id xyz' (it would make things easy, but well, it just doesn't work like this).
So, now I have the following questions:

  1. What is the current 'standard' way in which you and other webrtc developers solve this, as long stopping transceivers will not work in every browser? (chrome fixing it for current versions will probably take some time but being the most used browser, we cannot just ignore it)
  2. Did someone somehow (by abusing DTFM, using magic or whatever...) bodged a polyfill together? (I believe Adapter.js hasn't made this somehow possible)
  3. Is there another way besides muting=removing and sending remote-track-stop messages over the signaler? If not, what is the better option?

标签: google-chromewebrtc

解决方案


我最终做的是选择信号解决方案。我基本上会

// part of a method, that searches the transceiver to stop and assigned it to the 'transceiver' variable
peerconnection.removeTrack(transceiver.sender);
if (transceiver.direction === "sendrecv") transceiver.direction = "recvonly";
else transceiver.direction = "inactive";
signaler.send({type: 'transceiver:stop', data: transceiver.mid});

而在另一边

// received sent message and called this method with message.data
onTransceiverStopMessage(mid){
   const transceiverToStop = peerconnection.getTransceivers().filter(transceiver => transceiver.mid === mid);
   transceiverToStop.receiver.track.stop()
   transceiverToStop.receiver.track.dispatchEvent(new Event('ended'));
}

-CalldispatchEvent是必要的,因为stop在轨道上调用不会触发ended-Event。它适用于我的目的,但我仍在等待解决堆积不活动收发器的解决方案(因为它们仍然会影响性能,如 chrome 问题所述)


推荐阅读