WebRTC连接后为什么收不到对方的视频流?

司空艺诺 阅读 37

我在用 WebRTC 做一个简单的点对点视频通话 demo,信令服务器用的是 WebSocket,offer/answer 和 ICE 候选都正常交换了。本地流能显示,但 ontrack 回调一直没触发,远端视频就是出不来。

我检查了 RTCPeerConnection 的配置,也加了 ontrack 监听,但就是没反应。是不是漏了什么关键步骤?比如 addTrack 或者 setRemoteDescription 的顺序问题?

pc.ontrack = (event) => {
  console.log('收到远端流:', event.streams[0]);
  remoteVideo.srcObject = event.streams[0];
};

// 发送方
localStream.getTracks().forEach(track => {
  pc.addTrack(track, localStream);
});
我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
FSD-林莹
看起来你在发送方和接收方的代码都基本对了,但有几个细节容易出问题。首先检查下 setRemoteDescription 的调用顺序,必须在 addIceCandidate 之前。

async function handleOffer(offer) {
await pc.setRemoteDescription(new RTCSessionDescription(offer));
let answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
}


然后是 addTrack 和 ontrack 配合的问题。addTrack 后要等信令交互完成才能触发 ontrack。建议在 onicecandidate 里确认 ICE 连接状态:

pc.oniceconnectionstatechange = () => {
if (pc.iceConnectionState === 'connected') {
console.log('ICE 连接成功');
}
};


最后提醒下,某些浏览器需要用户交互(比如点击按钮)才能启动音视频采集,直接调用可能会被阻止。这可能是你收不到流的原因之一。试试在用户点击后再执行相关逻辑。
点赞
2026-03-31 16:04
皇甫统维
你这个问题很典型,十有八九是下面这几个地方没注意到:

1. createOffer 的时机太早

发送方必须在 addTrack 之后才能 createOffer,否则 offer 里根本没带轨道信息,对方当然收不到。

正确的顺序应该是:
// 发送方
localStream.getTracks().forEach(track => {
pc.addTrack(track, localStream);
});

// 添加完轨道后再创建 offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 然后通过信令服务器发给对方


2. 接收方 setRemoteDescription 的时机

接收方必须先 setRemoteDescription(offer),ontrack 才会触发。如果你先设置了 ontrack 监听,但还没 setRemoteDescription,那事件是不会来的。

// 接收方 - 收到 offer 后
await pc.setRemoteDescription(new RTCSessionDescription(offer));

// 然后创建 answer
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
// 通过信令服务器发给对方


3. 检查一下 createOffer 生成的 sdp

你可以 console.log 一下创建出来的 offer,看里面有没有 m=video 媒体描述,而且有没有 a=msid 字段。如果没有,那就是 addTrack 的时机问题。

4. 确认对方真的发送了数据

你可以在接收方加个监听看看连接状态:

pc.onconnectionstatechange = () => {
console.log('连接状态:', pc.connectionState);
};

pc.oniceconnectionstatechange = () => {
console.log('ICE状态:', pc.iceConnectionState);
};


如果显示 completed 或 connected,但 ontrack 还是没触发,那就是前面的顺序问题。如果一直是 checking 或 failed,那就是网络穿透的问题,跟代码顺序无关。

你先把 createOffer 放在 addTrack 之后试试,大概率是这个问题。
点赞
2026-03-14 11:01