为什么我的WebRTC P2P视频通话只能单向传输?
我在用WebRTC实现两人视频通话时,甲方能看见乙方画面,但乙方屏幕一直是黑的。已经检查过信令服务器和STUN/TURN配置没问题,双方都能收到SDP和ICE候选。这是客户端处理offer的代码:
function onOffer(offer) {
pc.setRemoteDescription(offer)
.then(() => pc.createAnswer())
.then(answer => pc.setLocalDescription(answer))
.then(() => signaling.sendAnswer(answer));
}
控制台报错”Failed to set remote answer in ontrack”,但调试时发现乙方收到的SDP里没有m=video轨道。奇怪的是甲方的offer里明明包含video媒体。这种单向传输的问题该怎么排查?
我遇到过类似情况,重点排查这几个点:
首先确认甲方生成offer前有没有真正拿到本地视频流并addTrack。比如:
如果漏了addTrack这一步,offer里虽然会生成m=video段,但标记为inactive或直接被忽略,对方解析时就看不到有效视频轨道。
然后是你贴的onOffer处理代码有个隐患:createAnswer之后没有检查answer.sdp是否真的包含m=video。你可以加个打印看看:
console.log(answer.sdp.includes('m=video'))如果返回false,说明远端offer里video轨道没生效,可能是因为setRemoteDescription时浏览器认为没有对应的stream track关联。
另外注意ontrack事件监听有没有写对。必须在pc上提前监听,不然会错过track事件:
pc.ontrack = (e) => { if (e.track.kind === 'video') remoteVideo.srcObject = e.streams[0]; }还有个小坑是某些浏览器(特别是Safari和旧版Chrome)在setRemoteDescription后不会立刻触发ontrack,要等完整的ICE连接建立才触发。建议同时监听iceconnectionstatechange看状态是否到connected。
最后那个“Failed to set remote answer in ontrack”错误,听起来像是你在ontrack里又调了setRemoteDescription?这肯定不对,ontrack是接收方收到流的回调,不应该在这里改SDP。检查下是不是事件处理嵌套错了。
我的做法是:两端都确保先addTrack再创建offer/answer,并在每一步前后打印localDescription和remoteDescription的sdp内容,对比看出哪一环video轨道消失了。这样基本能定位到具体步骤。
WebRTC的SDP协商是双向确认机制。即使你在offer中声明了video,如果接收方本地没有添加对应的媒体流track,PeerConnection在生成answer时会自动剔除video媒体描述,这是标准行为。你看到的"Failed to set remote answer in ontrack"错误也印证了这一点——ontrack事件触发时找不到对应track。
第一步要确认乙方是否在setRemoteDescription之前正确添加了本地媒体流。很多人以为只要对方发了offer带video,自己这边就会自动创建接收轨道,其实不是。你必须主动把本地音视频track加到RTCPeerConnection实例上。
注意我改了最后sendAnswer的部分,你原来的代码传的是未定义的answer变量,应该用pc.localDescription,因为setLocalDescription之后描述才会真正生效。
第二步检查SDP内容。虽然你说信令没问题,但建议在setRemoteDescription前后打印offer.sdp,确认里面真的包含m=video字段。有时候前端序列化/反序列化会出问题,比如JSON.stringify时把SDP对象搞丢了部分内容。
如果offer里确实有video但answer里没有,那基本可以确定是你没调addTrack。RTCPeerConnection会根据本地是否有sender track来决定是否响应相应媒体类型。
第三步是处理ontrack事件的方式。你应该在pc上监听ontrack,而不是依赖answer里的东西:
最后提醒一个常见坑:getUserMedia权限拒绝或静默失败。建议加上错误处理:
这样即使拿不到本地流,也能告诉对方“我能接收video”,避免answer里丢掉m=video段。
总结排查顺序:
先确认本地流是否addTrack → 检查offer和answer的完整SDP内容 → 确保ontrack监听正确设置 → 加transceiver兜底。95%的单向通话问题都是因为漏了addTrack或者getUserMedia失败没处理。