getstats() 返回一次性快照而非实时流,需 setinterval 每1–2秒轮询;关键带宽数据在 type==='transport' 报告中,丢包率需用 packetslost/packetssent 计算,移动端兼容性差且 promise 可能 reject。

getStats() 返回的是快照,不是实时流
调用 RTCPeerConnection.getStats() 得到的是一次性快照,不是持续推送的数据。如果你只调一次,大概率拿到的是连接刚建立时的“假象”——比如 availableOutgoingBitrate 显示 2.5 Mbps,但 2 秒后就掉到 600 kbps。必须用 setInterval 主动轮询,频率建议 1–2 秒一次,太密会拖慢主线程,太疏会错过关键拐点。
别依赖首次返回值;尤其在移动热点或企业内网下,拥塞控制收敛慢,前 3–5 秒的统计基本不准。
过滤 transport 类型才能看到真实可用带宽
很多人查 getStats() 时遍历所有 report,结果盯着 media-source 或 track 下的 availableOutgoingBitrate 干着急——那只是编码器“想发”的上限,不是网络栈“允许发”的上限。真正管用的字段藏在 type === 'transport' 的 report 里。
- 用
stats.forEach(report => { if (report.type === 'transport') { console.log(report.availableOutgoingBitrate); } })提取 - Chrome 120+ 对该值更保守,弱网下比旧版低 20%~40%,别拿老文档的阈值硬套
- 持续低于 800 kbps 就该触发降级逻辑,不是等卡顿再反应
丢包、抖动、重传这些关键指标得手动算
getStats() 不直接暴露“丢包率”这种友好数字,得靠原始字段自己推:
-
packetsLost和packetsSent在outbound-rtpreport 中,丢包率 =packetsLost / packetsSent -
jitter单位是秒,值 > 0.03 表示明显抖动(30ms),音频会断续 -
nackCount和pliCount高,说明接收端频繁请求重传或关键帧,是网络不稳的强信号 - 注意:iOS Safari 16.4 之前不支持
nackCount,得 fallback 到retransmittedPacketsSent
移动端要注意 stats 结构兼容性
Android Chrome 和 iOS Safari 对 getStats() 返回结构的处理差异很大:
- iOS Safari 16.4+ 才完整支持
transport类型和availableOutgoingBitrate字段,旧版本返回undefined是正常现象 - 某些 Android WebView(如微信内置)会把
outbound-rtp拆成多个 report,ssrc不唯一,得靠mediaType === 'video'+kind === 'video'双重过滤 - 别假设
stats.get('some-id')一定存在——先stats.forEach遍历,再按type和mediaType筛选,否则部分机型静默失败
最常被忽略的一点:getStats() 的 promise 可能被 reject(比如连接已关闭),但错误不抛到控制台,得显式 catch;另外,availableOutgoingBitrate 在连接刚建立时可能为 null,直接除法会报 NaN,得加空值判断。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











