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
相关产品推荐
相关产品推荐

