You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PeerJS实现音视频通话时客户端无法显示推流端返回的流如何解决

问题原因及对应解决方案

1. 核心问题:SDP协商未包含视频轨道

客户端发起呼叫时仅传入了仅含音频的流,PeerJS默认生成的SDP offer只会协商音频的收发能力,没有预留视频轨道的协商位置。即便推流端返回了带视频的流,客户端WebRTC栈也不会处理额外的视频轨道,导致视频无法渲染。
解决方法:发起呼叫时主动指定协商配置,强制要求开启视频接收能力,修改客户端呼叫逻辑:

public callToPeer(peerId, localClientStream) {
  // 新增协商配置,强制要求接收视频轨道
  const callOptions = {
    offerOptions: {
      offerToReceiveAudio: true,
      offerToReceiveVideo: true
    }
  };
  this.outGoingCall = this.peer.call(peerId, localClientStream, callOptions);
  this.outGoingCall.on('stream', (remoteStream: MediaStream) => {
      console.log('incoming stream from streamer ', remoteStream);
      this.incomingStream.next(remoteStream);
    });
}

2. 浏览器自动播放策略拦截

大部分现代浏览器禁止带音频的视频自动播放,仅配置autoplay属性会被浏览器拦截播放,导致无画面。
解决方法:修改客户端video标签,新增muted、playsinline属性适配PC和移动端规则:

<div class="call-holder" *ngIf="incomingStream | async as stream">
  <video [srcObject]="stream" autoplay muted playsinline></video>
...
</div>

如果需要播放音频,可以在用户交互(比如点击页面按钮)后手动将video的muted属性设为false即可。

3. Angular异步变更检测未触发(低概率)

PeerJS的回调事件默认运行在Angular的NgZone之外,更新BehaviourSubject后可能不会触发视图刷新,即便值更新了页面也不会渲染。
解决方法:将流更新逻辑包裹在NgZone.run中:
首先在构造函数注入NgZone:

constructor(private ngZone: NgZone) {}

修改流接收回调:

this.outGoingCall.on('stream', (remoteStream: MediaStream) => {
  console.log('incoming stream from streamer ', remoteStream);
  this.ngZone.run(() => {
    this.incomingStream.next(remoteStream);
  });
});

验证方法

可在客户端收到流时打印remoteStream.getVideoTracks(),检查是否返回了有效视频轨道,轨道的enabled和readyState属性是否为true和live状态,确认流本身无异常。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 03:36:02