跳到主要内容

媒体引擎与QoS

WebRTC 的工业级护城河在媒体引擎:拥塞控制、抗丢包、Simulcast/SVC、自适应。本目录把这一套讲透。

阅读顺序(计划)

顺序文件解决的问题
1拥塞控制GCC与TWCC.md为什么需要拥塞控制;GCC 与 TWCC 工作原理
2抗丢包NACK-RTX-FEC.mdNACK / RTX / RED / ULPFEC / FlexFEC
3关键帧请求PLI与FIR.md何时需要关键帧;谁触发
4Simulcast与SVC.md多分辨率上行、时域/空域分层
5音频3A处理.mdAEC / NS / AGC 与跨平台差异
6getStats全字段速查.md全字段含义与排障对照

心智模型

发送端 接收端
─── 编码 ───► RTP/SRTP 包 ─── 网络 ───► 抖动缓冲 ─── 解码 ─── 渲染
▲ │
│ 码率调整 丢包/抖动/RTT
└──── 拥塞控制 ◄── TWCC/REMB ◄────┘
GCC / pacer NACK / PLI / FIR
FEC 恢复

四个关键环节:

  1. 拥塞控制:根据 RTT / 丢包 / 排队延迟估带宽,调码率。
  2. 抗丢包:NACK 重传 + FEC 前向纠错,保证可解码。
  3. 关键帧管理:PLI/FIR 触发 I 帧,让落后的接收端跟上。
  4. 自适应:Simulcast 多档上行 + SVC 分层,让 SFU 按需转发。

一句话指标

指标健康阈值看 stats 字段
RTT< 200mscurrentRoundTripTime
丢包率< 2%packetsLost / packetsReceived
帧率> 24framesPerSecond
卡顿次数单分钟 ≤ 1freezeCount
抖动< 30msjitter
可用上行> 当前码率 1.2 倍availableOutgoingBitrate

关键 stats 字段(最小集)

const stats = await pc.getStats();
for (const r of stats.values()) {
switch (r.type) {
case 'inbound-rtp': /* 收:packetsLost, framesPerSecond, jitterBufferDelay, freezeCount, totalPausesDuration */ break;
case 'outbound-rtp': /* 发:bytesSent, framesEncoded, qualityLimitationReason, targetBitrate */ break;
case 'remote-inbound-rtp':/* 对端反馈:roundTripTime, fractionLost */ break;
case 'candidate-pair': /* 当前路径:currentRoundTripTime, availableOutgoingBitrate */ break;
case 'media-source': /* 采集源:width, height, framesPerSecond */ break;
}
}

详细字段说明见 getStats全字段速查.md(编写中)。

拥塞控制速记

  • GCC(Google Congestion Control):早期方案,基于 REMB 反馈。
  • TWCC(Transport-wide Congestion Control):现代默认。每个 RTP 包带 transport-cc 扩展头,接收端定期把"包的到达时间"打包回传发送端,发送端做卡尔曼滤波或 trendline 估计带宽。
  • 没有 TWCC = SFU 无法做精细的码率自适应。

抗丢包优先级

丢包率推荐策略
< 1%NACK + 重传足够
1%~5%NACK + 部分 FEC
5%~10%NACK + FlexFEC + 降分辨率
> 10%切到关键帧间隔更小 + 降到最低层

反模式

反模式后果
不开 TWCC 扩展头SFU 拿不到全链路反馈
关 NACK 想省带宽普通丢包就花屏
一档上行硬扛多人高端订阅者吃低端发送方的码率
maintain-resolution 用在会议视频帧率掉到个位数
不监控 qualityLimitationReason不知道是 CPU 还是带宽限制

权威资料