如何检测WebRTC场景下的视频流冻结与黑屏异常
视频流异常自动检测方案
1. 接收端帧统计检测
这是稳定性最高、性能消耗最小的通用检测方案,直接通过WebRTC原生统计接口判断流状态:
- 定期调用
peerConnection.getStats()方法,筛选类型为inbound-rtp且kind为video的统计项 - 对比前后两次统计的
framesReceived、framesDecoded字段,如果连续3~5个检测周期(建议单周期1s)数值没有增长,即可判定为视频流冻结 - 如果
framesDecoded长期为0但packetsReceived持续增长,即可判定为解码失败导致的黑屏
let lastFramesDecoded = 0; let freezeCount = 0; const checkVideoException = async (pc) => { const stats = await pc.getStats(); stats.forEach(report => { if (report.type === 'inbound-rtp' && report.kind === 'video') { if (report.framesDecoded === lastFramesDecoded) { freezeCount++; if (freezeCount >= 3) { // 触发异常处理逻辑:自动重连/提示用户等 console.log('检测到视频流冻结/黑屏'); } } else { freezeCount = 0; lastFramesDecoded = report.framesDecoded; } } }) } // 每1秒执行一次检测 setInterval(() => checkVideoException(yourPeerConnection), 1000);
2. 渲染层像素对比检测
该方案更贴近用户实际看到的渲染效果,可作为统计检测的补充校验:
- 对
RTCVideoView组件做定期截图,提取图像像素数据 - 对比相邻两次截图的像素方差,如果连续多个周期方差低于预设阈值(几乎没有像素变化),即可判定为冻结
- 如果所有像素数值都为0,直接判定为黑屏
注意:该方案性能消耗更高,建议检测周期设置为3s以上,不要作为核心检测逻辑使用
3. 发送端上行状态检测
需要同步排查推流端故障导致的全局异常:
- 调用
getStats()筛选类型为outbound-rtp且kind为video的统计项 - 监控
framesCaptured、framesSent字段的增长情况,如果停止增长说明本地采集/推流异常 - 同时检查本地
MediaStream的视频轨道状态,readyState变为ended说明轨道已失效
4. 配套自动修复逻辑
检测到异常后可搭配对应逻辑降低用户感知:
- 本地采集异常:先尝试重启本地摄像头轨道,替换PeerConnection中对应的发送轨道
- 远端接收异常:先触发ICE重连或者SDP重新协商,仍未恢复再提示用户重新进入通话
- 渲染层异常:先卸载再重新挂载
RTCVideoView组件,排除RN端渲染组件内部故障
内容的提问来源于stack exchange,提问作者Falaen
相关产品推荐
相关产品推荐

