如何在WebRTC单个RTCPeerConnection中添加多路轨道并解决Firefox兼容问题?
解决Firefox中RTCPeerConnection双视频轨道仅触发一次ontrack的问题
这个问题我之前帮不少开发者排查过,Firefox和Chrome在处理同类型(都是视频)轨道的逻辑确实存在差异,咱们一步步拆解解决:
问题根源
Chrome会为每个添加的轨道单独触发一次ontrack事件,每个事件对应一个只包含单轨道的MediaStream;但Firefox的行为是将同类型的多个轨道合并到同一个MediaStream中,所以只会触发一次ontrack事件,所有视频轨道都包含在该事件的streams属性对应的流里。
解决方案
不需要额外做协商重连(你在创建Offer前添加轨道的操作本身是对的),只需要修改接收端的ontrack事件处理逻辑,遍历流中的所有轨道即可。
发送端代码(保持你的逻辑即可,无需修改)
// 假设已获取普通视频流cameraStream和画布捕获流canvasStream const peerConnection = new RTCPeerConnection(); // 添加两路视频轨道 cameraStream.getVideoTracks().forEach(track => { peerConnection.addTrack(track, cameraStream); }); canvasStream.getVideoTracks().forEach(track => { peerConnection.addTrack(track, canvasStream); }); // 后续创建Offer、设置本地描述等流程不变 const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); // 将offer发送给远端...
接收端代码(关键修改)
const remotePeerConnection = new RTCPeerConnection(); remotePeerConnection.ontrack = (event) => { // 遍历事件中的所有流 event.streams.forEach(stream => { // 提取流中的所有视频轨道 const videoTracks = stream.getVideoTracks(); // 根据轨道顺序区分两路视频(发送端添加的顺序会保留) videoTracks.forEach((track, index) => { if (index === 0) { // 第一个轨道:普通视频流 document.getElementById('camera-video').srcObject = new MediaStream([track]); } else if (index === 1) { // 第二个轨道:画布捕获流 document.getElementById('canvas-video').srcObject = new MediaStream([track]); } }); }); }; // 后续接收Offer、设置远程描述等流程不变
额外排查技巧
如果还是有问题,可以通过以下步骤确认:
- 发送端打印
peerConnection.getSenders(),确认存在两个视频发送器,说明轨道已成功添加; - 接收端在
ontrack事件中打印event.streams和每个流的getVideoTracks(),确认是否包含两个视频轨道; - 也可以尝试用
addTransceiver显式添加轨道,兼容性可能更好:// 发送端替换addTrack为addTransceiver const cameraTrack = cameraStream.getVideoTracks()[0]; const canvasTrack = canvasStream.getVideoTracks()[0]; peerConnection.addTransceiver(cameraTrack, { direction: 'sendrecv' }); peerConnection.addTransceiver(canvasTrack, { direction: 'sendrecv' });
内容的提问来源于stack exchange,提问作者Ryehl
相关产品推荐
相关产品推荐

