WebRTC 多视频流中如何停止 track 以降低带宽占用
RTCRtpReceiver 本身没有停止网络接收的方法。设置:
receiver.track.enabled = false;
只会让本地轨道停止输出视频,通常表现为黑屏,但不会通知发送端停止发送,所以带宽仍然被占用。
真正停止某一路视频,需要通过 RTCRtpTransceiver 修改 SDP 方向,并重新协商。
1. 暂停指定视频流
根据 SDP 中的 mid 找到对应的 transceiver:
const transceiver = pc .getTransceivers() .find(t => t.mid === 'video1'); if (transceiver) { transceiver.direction = 'inactive'; await renegotiate(); }
重新协商的示例:
async function renegotiate() { const offer = await pc.createOffer(); await pc.setLocalDescription(offer); // 通过你的信令通道把 offer 发给后端 const answer = await sendOfferToBackend(offer); await pc.setRemoteDescription(answer); }
协商完成后,video1 对应的 m-line 应该变为:
a=mid:video1 a=inactive
此时该路视频不应再传输 RTP 数据,带宽会被释放。
2. 恢复指定视频流
需要重新观看时,把方向改回 recvonly,然后再次协商:
transceiver.direction = 'recvonly'; await renegotiate();
因为当前端只接收视频,所以使用 recvonly。后端对应的应答方向通常应为 sendonly。
3. 永久停止某一路视频
如果以后不再需要这一路,可以停止 transceiver:
const transceiver = pc .getTransceivers() .find(t => t.mid === 'video1'); transceiver.stop(); await renegotiate();
注意:调用 stop() 后,这个 transceiver 不能再恢复。后续如果要重新接收该视频,需要新建 transceiver 或重新建立 RTCPeerConnection,并且后端必须支持新增视频流的协商。
4. 后端必须配合
如果后端忽略 a=inactive,仍然继续发送 RTP,那么浏览器端无法仅通过 RTCRtpReceiver 阻止数据到达。此时需要:
- 后端支持 SDP 重协商,并在收到
inactive后停止对应 sender; - 或通过业务信令通知后端停止指定视频流;
- 或在建立连接时只协商用户需要的视频 m-line;
- 如果后端不支持重协商,只能关闭并重新创建包含所需视频流的
RTCPeerConnection。
下面这些本地操作都不能真正节省下行带宽:
track.enabled = false; track.stop(); videoElement.srcObject = null;
不要使用 track.enabled = false 来停止网络传输。应通过 RTCRtpTransceiver 将对应视频的 direction 设置为 inactive,并完成一次 SDP 重协商。这样后端停止发送后,该路轨道才不会继续占用带宽。需要恢复时,再将方向改回 recvonly 并重新协商。
内容的提问来源于stack exchange,提问作者Christoph Acs

