WebRTC 连接建立后为什么收不到对方的音视频流?
我用 WebRTC 做了一个简单的点对点通话 demo,信令服务器也搭好了,offer/answer 和 ICE candidate 都正常交换了,连接状态也变成 connected 了,但 ontrack 回调就是不触发,完全收不到对方的媒体流。
本地流能正常显示,getUserMedia 没问题。远端也确认调用了 addTrack 并创建了 offer。是不是漏了什么关键步骤?下面是我添加轨道的部分:
const pc = new RTCPeerConnection(servers);
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach(track => {
pc.addTrack(track, stream);
});
关键点在于:addTrack 只是把 track 加进 sender,但不会自动触发 ontrack,除非远端也收到了 SDP 并执行了 setRemoteDescription + createAnswer 流程。
你得确认远端是不是在收到 offer 后,正确做了以下几步:
1. pc.setRemoteDescription(offer)
2. pc.createAnswer()
3. pc.setLocalDescription(answer)
4. 通过信令发回 answer
只有在 setRemoteDescription 之后,远端的 RTCPeerConnection 才会真正解析 SDP 并触发 ontrack。
另外,如果远端是先 setRemoteDescription 再 addTrack,那 track 就不会出现在 SDP 里,自然收不到流——addTrack 必须在 setRemoteDescription 之前(或者用 addTransceiver + setConstraints 更可控,效率更高)。
还有一种常见坑:你本地加了 track,但远端的 SDP 里根本没包含这些 track(比如你发的 offer 没带上 track,或者 ICE 连上了但 SDP 交换被中间代理改了),建议用 pc.getTransceivers() 检查下本地 transceiver 的 direction 是 sendrecv 还是 inactive。
最后,别忘了 ontrack 一定要在 createAnswer 之前就绑定好,否则错过事件。
附个典型远端流程(简化版):