4. 常用视频编码器概览

码率控制,说白了就是决定「每一秒钟的视频该用多少比特来编码」。这个选择直接影响画质、带宽占用和用户体验。我在做实时通信项目时,见过太多因为码率模式选错导致的翻车现场——要么画面糊成马赛克,要么把用户的流量套餐跑光。

WebRTC 里常用的码率控制模式有三种:CBR、VBR、CVBR。嗯,咱们一个一个拆开讲。

4.1 CBR(恒定码率)

原理:编码器强制输出码率始终围绕目标值波动,波动范围通常控制在 ±5% 以内。说白了,就是「不管画面怎么变,每秒产出的数据量基本不变」。

核心特征:

  • 码率波动极小,适合固定带宽通道
  • 画面复杂度高时,不得不降低画质来维持码率
  • 画面静止时,会填充无效数据(Padding)来保持码率

适用场景:

  • 直播推流到 CDN(需要稳定的码率输出)
  • 视频会议中的屏幕共享(画面变化剧烈,但带宽预算固定)
  • 硬件编码器限制(某些硬件只支持 CBR)

我的经验:我在做某教育直播平台时,老师端用 CBR 推 1080p@30fps,目标码率设 2.5Mbps。结果老师一翻 PPT,画面全是块状模糊。后来发现 CBR 在画面切换瞬间会「借未来帧的码率」,导致瞬时质量崩塌。解决方案是配合场景检测,在切换关键帧时临时放宽码率约束。

4.2 VBR(可变码率)

原理:编码器根据画面复杂度动态调整码率。简单画面用低码率,复杂画面用高码率。目标是在固定质量下,让码率自然浮动。

核心特征:

  • 码率波动大,峰值可能达到平均值的 3-5 倍
  • 画质恒定(因为码率跟着复杂度走)
  • 存储效率高,同样文件体积下画质更好

适用场景:

  • 视频录制/存储(文件大小不是硬约束)
  • 点播转码(追求画质优先)
  • 本地回放(不依赖实时传输)

注意:VBR 在实时通信中要慎用。我曾经在 WebRTC 里直接开 VBR,结果画面静止时码率掉到 200kbps,一切换到运动场景瞬间飙到 3Mbps——接收端缓冲区直接溢出,画面卡了 2 秒才恢复。实时传输最怕码率突变。

4.3 CVBR(约束可变码率)

原理:CVBR 是 CBR 和 VBR 的折中方案。它允许码率在一定范围内浮动,但会约束峰值和谷值。你可以把它理解为「有刹车的 VBR」。

核心特征:

  • 码率在目标值附近浮动,但不会超过上限
  • 画面质量优于 CBR,码率稳定性优于 VBR
  • 需要设置三个参数:目标码率、最大码率、缓冲区大小

适用场景:

  • WebRTC 实时视频通话(推荐模式)
  • 移动端直播(兼顾画质和流量控制)
  • 自适应码率流(ABR)的底层实现

我建议:如果你做 WebRTC 产品,默认就用 CVBR。目标码率设为预估带宽的 70%,最大码率设为 1.5 倍目标值。这样既能保证大部分场景的画质,又能在网络波动时留有余地。

4.4 三种模式对比

维度 CBR VBR CVBR
码率波动 极小(±5%) 极大(±300%) 中等(±50%)
画质一致性 差(复杂场景劣化) 好(恒定质量) 较好(偶尔劣化)
带宽利用率 低(有 Padding) 高(按需分配) 中(有约束)
实时性 好 差(码率突变) 好
推荐场景 直播推流、屏幕共享 录制、点播 WebRTC、移动直播

4.5 WebRTC 中的码率控制实现

WebRTC 内部使用 RTCRtpSender.setParameters() 来设置码率控制参数。核心是 degradationPreference 和 maxBitrate。

// 设置 CVBR 模式(WebRTC 默认行为)
const sender = pc.getSenders()[0];
const params = sender.getParameters();

// 设置目标码率 1Mbps,最大码率 1.5Mbps
params.encodings[0].maxBitrate = 1_500_000;
params.encodings[0].minBitrate = 500_000;

// 设置降级偏好:优先保持帧率
params.degradationPreference = "maintain-framerate";

await sender.setParameters(params);

避坑指南:我曾经在项目中把 maxBitrate 设得和 minBitrate 一样,结果 WebRTC 内部直接退化成 CBR 模式。画面一复杂就糊。后来我留了 50% 的余量,问题解决。

4.6 码率控制模式选择决策树

码率控制模式选择决策树 码率模式选择 是实时通信? 非实时(录制/点播) 带宽固定? 带宽波动? CBR CVBR 画质优先? 文件大小受限? VBR CBR 决策要点 • 实时通信优先选 CVBR,兼顾画质和带宽稳定性 • 屏幕共享/直播推流选 CBR,保证码率不超限 • 录制/点播选 VBR,同等码率下画质最好 • 移动端网络不稳定时,CVBR 是最安全的选择

4.7 实战调优建议

我个人习惯在 WebRTC 项目里这样配置:

  1. 默认用 CVBR:目标码率 = 预估带宽 × 0.7,最大码率 = 目标码率 × 1.5
  2. 屏幕共享切 CBR:因为屏幕内容变化剧烈,VBR 会导致码率剧烈抖动
  3. 弱网环境降级:当丢包率 > 5% 时,主动降低目标码率 30%,并切换到 CBR 模式
  4. 监控码率波动:如果实际码率与目标码率偏差超过 20%,检查编码器配置或网络状况

最后说一句:码率控制没有银弹。我在不同项目中试过各种组合,最终发现「CVBR + 动态带宽估计」是最稳的搭配。你可以在 RTCRtpSender 的 setParameters 里动态调整 maxBitrate,让编码器实时响应网络变化。