WebRTC媒体收发实现及从addTrack迁移到addTransceiver的问题
WebRTC从addTrack迁移到addTransceiver的问题解答
问题1:如何从yourConn对等端接收媒体?能否实现Peer1向Peer2发送、Peer1同时接收Peer2媒体且无需重新协商?
- 接收媒体的前提是对方对等端已添加待发送的媒体轨道,且双方完成SDP协商与ICE连接。
- 可以实现双向媒体传输且无需额外协商,但初始创建Transceiver时必须指定正确的
direction参数。默认情况下,addTransceiver(track)的direction是sendonly,仅能发送无法接收。如果需要双向传输,初始化时直接设置为sendrecv:
yourConn.addTransceiver(streams.getAudioTracks()[0], { direction: 'sendrecv' });
这样初始SDP协商就会同时建立发送和接收通道,后续只要在同一Transceiver下替换轨道,无需重新协商。如果初始设为sendonly,之后再修改为sendrecv,则必须重新协商。
问题2:双方ontrack事件应如何处理?若需要,是否应在其中使用addTrack?
ontrack事件的核心是接收对方发送的媒体轨道,并绑定到本地播放元素,完全不需要在其中调用addTrack(addTrack是用于向对等端发送媒体的API,和接收逻辑无关)。- 标准的ontrack处理示例:
// Peer1 接收Peer2的媒体 let peer1ReceiveStream; yourConn.ontrack = (e) => { if (!peer1ReceiveStream) { peer1ReceiveStream = new MediaStream(); // 假设页面有id为remoteAudio的audio元素 document.getElementById('remoteAudio').srcObject = peer1ReceiveStream; } peer1ReceiveStream.addTrack(e.track); }; // Peer2 接收Peer1的媒体同理 let peer2ReceiveStream; yourConn2.ontrack = (e) => { if (!peer2ReceiveStream) { peer2ReceiveStream = new MediaStream(); document.getElementById('localRemoteAudio').srcObject = peer2ReceiveStream; } peer2ReceiveStream.addTrack(e.track); };
- 不要在
ontrack回调中修改Transceiver方向或执行轨道替换操作,这类发送相关的逻辑应该在需要主动发送媒体时单独处理。
问题3:yourConn2的ontrack事件代码是否合理?是否应通过getTransceivers获取Transceiver后操作?
首先指出当前代码的几个错误:
ontrack回调默认是同步函数,直接使用await会报错(若要使用async需将回调声明为async (e) => {},但不推荐在事件回调中直接用async);e.transceiver.sender.replaceTrack(remoteStream)参数错误:replaceTrack要求传入MediaStreamTrack,而非MediaStream;- 在
ontrack中修改Transceiver方向并替换轨道逻辑不合理:ontrack是接收事件,此时的Transceiver用于接收对方媒体,发送本地媒体应使用主动创建的Transceiver。
关于是否用getTransceivers的方式:
- 若要让Peer2向Peer1发送媒体,正确做法是主动在Peer2端创建sendrecv方向的Transceiver并关联本地轨道,而非在接收事件中修改:
// Peer2主动添加用于发送的Transceiver const localAudioTrack = localStream.getAudioTracks()[0]; const transceiver = yourConn2.addTransceiver(localAudioTrack, { direction: 'sendrecv' }); // 后续需要替换轨道时 await transceiver.sender.replaceTrack(newLocalAudioTrack);
- 如果确实需要将已存在的recvonly方向Transceiver改为sendrecv,可以通过
getTransceivers获取后修改,但修改方向后必须重新协商(调用createOffer/setLocalDescription并交换SDP)。另外注意拼写错误:reciever应为receiver,且receiver.replaceTrack不存在,替换发送轨道需用sender.replaceTrack。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

