WebRTC Transceiver异常:recvonly Transceiver意外创建
WebRTC Transceiver 重复创建问题分析与解决
问题现象
尝试通过Transceiver在两个WebRTC对等端间建立音频流,预期两端各存在一个sendrecv方向的Transceiver,但实际remoteConnection中出现两个Transceiver:
- 一个mid为null的
sendrecvTransceiver - 协商过程中自动生成的
recvonlyTransceiver
问题原因
1. 冗余协商操作打乱流程
代码中提前执行了remoteConnection.createOffer()并设置本地描述,完全违背WebRTC标准协商流程。正常流程应由一端发起offer,另一端回应answer,提前在remote端创建offer会让其处于异常会话状态,后续处理local端发来的offer时,无法正确匹配已手动创建的Transceiver,导致WebRTC自动生成新的recvonly Transceiver适配远端媒体流。
2. 错误的Track关联逻辑
remote端的Transceiver调用replaceTrack时传入了localStream的音频轨道,逻辑上属于交叉绑定错误(remote端应使用自身媒体轨道),虽不是直接导致多Transceiver的原因,但会干扰会话状态的正常同步。
解决方案
1. 修复协商流程
移除remote端提前创建offer的冗余代码,严格遵循local发起offer → remote接收并生成answer → local接收answer的标准流程。
2. 正确配置Transceiver与Track
确保两端的Transceiver绑定自身的媒体轨道,避免交叉绑定错误。
修正后的完整代码
<!DOCTYPE html> <html> <body> <h2>WebRTC with Transceivers on Both Peers</h2> <button onclick="startConnection()">Start Connection</button> <script> let localConnection; let remoteConnection; let localStream; let remoteStream; async function startConnection() { // 获取本地音频流 localStream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 为remote端模拟本地流(测试用,实际场景从remote端获取) const remoteMockStream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 创建对等连接 localConnection = new RTCPeerConnection(); remoteConnection = new RTCPeerConnection(); // ICE候选处理 localConnection.onicecandidate = (e) => { if (e.candidate) remoteConnection.addIceCandidate(e.candidate); }; remoteConnection.onicecandidate = (e) => { if (e.candidate) localConnection.addIceCandidate(e.candidate); }; // 配置local端Transceiver const localTransceiver = localConnection.addTransceiver('audio', { direction: 'sendrecv', }); localTransceiver.sender.replaceTrack(localStream.getAudioTracks()[0]); // 配置remote端Transceiver const remoteTransceiver = remoteConnection.addTransceiver('audio', { direction: 'sendrecv' }); remoteTransceiver.sender.replaceTrack(remoteMockStream.getAudioTracks()[0]); // 处理remote端收到的轨道 remoteStream = new MediaStream(); remoteConnection.ontrack = (event) => { remoteStream.addTrack(event.track); console.log('Received remote audio track'); const remoteAudio = document.createElement('audio'); remoteAudio.srcObject = remoteStream; remoteAudio.autoplay = true; document.body.appendChild(remoteAudio); }; // 标准协商流程 const offer = await localConnection.createOffer(); await localConnection.setLocalDescription(offer); await remoteConnection.setRemoteDescription(offer); const answer = await remoteConnection.createAnswer(); await remoteConnection.setLocalDescription(answer); await localConnection.setRemoteDescription(answer); console.log('local Transceivers:', localConnection.getTransceivers()) console.log('remote Transceivers:', remoteConnection.getTransceivers()) console.log('WebRTC connection established with transceivers on both sides.'); } </script> </body> </html>
验证结果
修正后,两端的getTransceivers()都会返回一个sendrecv方向的Transceiver,mid正常赋值,不会出现额外的自动创建Transceiver。
内容的提问来源于stack exchange,提问作者Oleg Dobrygin
相关产品推荐
相关产品推荐

