3. 码率控制核心概念

CBR,全称 Constant Bit Rate,恒定码率。说白了,就是让编码器输出一个几乎不变的码率。你设定了 2 Mbps,它就老老实实按 2 Mbps 往外吐数据,上下浮动很小。

我刚开始接触视频编码时,觉得 CBR 很简单——不就是固定码率嘛。后来踩了坑才发现,这里面的门道比想象中多得多。尤其是填充比特和跳帧这两个机制,搞不清楚的话,直播画面会出大问题。

CBR 的工作原理

CBR 的核心逻辑就一句话:码率是目标,质量是代价。

编码器会持续监控输出码率。如果当前码率低于目标值,它就通过调整量化参数(QP)来降低压缩强度,让画面保留更多细节,从而增加数据量。反过来,如果码率超标了,它就提高 QP,牺牲画质来压缩数据量。

但这里有个关键问题:视频内容复杂度是实时变化的。一个静态的新闻主播画面,信息量很少,编码器很容易就能压到目标码率以下。而一个快速运动的足球比赛画面,信息量爆炸,编码器拼命压也压不住。

当码率压不住时,CBR 有两个应对手段:

  • 填充比特:码率太低时,往数据流里塞无意义的填充数据,凑够目标码率。
  • 跳帧:码率太高时,直接丢掉某些帧,强行降低码率。

这两个机制,一个浪费带宽,一个破坏流畅度。但 CBR 就是这样——它优先保证码率恒定,其他都是次要的。

核心理解:CBR 不是「让画面质量恒定」,而是「让码率恒定」。质量可以波动,码率必须稳定。

填充比特与跳帧机制

填充比特

填充比特,英文叫 Padding。编码器在输出码流时,如果实际编码产生的数据量小于目标码率,就往码流里插入一些无意义的字节。这些字节解码器会直接忽略,不包含任何图像信息。

我见过不少新手问:「填充比特不是浪费带宽吗?」
嗯,确实是浪费。但你要明白,CBR 的设计初衷就是码率恒定。在某些场景下,比如老旧的传输系统,接收端要求数据流必须严格匀速到达。没有填充比特,码率就会忽高忽低,接收端可能直接崩溃。

填充比特的典型场景:

  • 简单画面(如纯色背景、静态字幕)
  • 低运动量的访谈节目
  • 码率设置远高于内容复杂度需求时

我的经验:我曾经在做一个监控项目时,发现编码后的文件比预期大了 30%。排查了半天,发现是填充比特在作祟。画面太简单,编码器压得太狠,结果大量填充比特把码率「填」回了目标值。后来我调低了目标码率,问题就解决了。

跳帧

跳帧,英文叫 Frame Skipping。当画面复杂度超出编码器的处理能力,码率即将超标时,编码器会直接丢弃某些帧。这些帧不编码、不传输,解码端自然也就看不到。

跳帧的后果很明显:画面卡顿、掉帧、不流畅。

为什么会触发跳帧?

  • 场景剧烈切换(如镜头快速摇动)
  • 高运动量内容(如体育赛事、动作电影)
  • 目标码率设置过低,无法承载内容复杂度

注意:跳帧是 CBR 的「最后手段」。一旦触发跳帧,用户体验会急剧下降。直播场景中,跳帧意味着观众会看到画面「卡住」或「跳过去」。我个人建议,在直播配置中尽量避免触发跳帧。

CBR 在直播场景中的应用

直播是 CBR 的主战场。为什么?因为直播的传输通道通常是固定的。

你想想看,一个直播流从推流端到 CDN,再到观众端,中间经过无数个网络节点。每个节点都有带宽限制。如果码率忽高忽低,很容易造成网络拥塞或丢包。CBR 的恒定码率特性,正好解决了这个问题。

直播场景中 CBR 的典型应用:

  • RTMP 推流:大部分直播平台要求推流码率稳定,CBR 是默认选择
  • 视频会议:带宽有限且固定,CBR 保证通话不中断
  • IPTV/有线电视:传输带宽预先分配,CBR 确保每个频道不超限
  • 监控摄像头:存储空间有限,CBR 便于估算录像时长

但直播场景也有个坑:CBR 对复杂场景的适应性差。

我记得有一次做游戏直播的编码优化。游戏画面在静止时很清晰,但一到团战场景,画面就糊成一团,还偶尔卡顿。这就是 CBR 的典型问题——码率恒定,但画面复杂度波动大,导致质量不稳定。

后来我用了 VBR 配合码率限制,效果好了很多。但这是后话了,后面章节会详细讲。

CBR 的参数配置

CBR 的核心参数有三个:-b:v、-bufsize、-maxrate。这三个参数配合使用,才能实现真正的 CBR。

-b:v:目标码率

-b:v 是目标码率,单位通常是 bit/s。比如 -b:v 2M 表示目标码率 2 Mbps。

这是 CBR 最直接的参数。你设多少,编码器就尽量往这个值靠拢。

ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -bufsize 2M -maxrate 2M output.mp4

-bufsize:缓冲区大小

-bufsize 是编码器的虚拟缓冲区大小。它决定了编码器允许码率波动的范围。

我习惯把 -bufsize 理解为「容忍度」。缓冲区越大,编码器越能容忍码率的短期波动;缓冲区越小,码率越严格恒定。

举个例子:

  • -bufsize 2M:缓冲区等于目标码率,码率波动范围较小
  • -bufsize 4M:缓冲区是目标码率的两倍,码率波动范围更大
  • -bufsize 1M:缓冲区小于目标码率,码率控制更严格,但更容易触发跳帧

我的建议:直播场景中,-bufsize 通常设置为目标码率的 1 倍到 2 倍。设置太小容易跳帧,设置太大又失去了 CBR 的意义。我一般用 -bufsize 1.5 * -b:v 作为起点。

-maxrate:最大码率

-maxrate 是编码器允许的最大瞬时码率。在 CBR 模式下,-maxrate 通常设置为与 -b:v 相同或略高。

为什么需要 -maxrate?因为编码器在复杂场景下会尝试提高码率来保持画质。如果不限制最大码率,瞬时码率可能飙升,导致网络拥塞。

CBR 的标准配置:

ffmpeg -i input.mp4 -c:v libx264 \
  -b:v 2M \
  -bufsize 2M \
  -maxrate 2M \
  -nal-hrd cbr \
  output.mp4

注意最后那个 -nal-hrd cbr。这个参数告诉编码器严格按照 CBR 模式工作,包括填充比特和跳帧机制。不加这个参数,编码器可能只是「近似 CBR」,而不是严格的 CBR。

参数对比表

参数 作用 典型值(直播场景) 注意事项
-b:v 目标码率 1M ~ 8M(视分辨率而定) 设置过低会导致画质差或跳帧
-bufsize 缓冲区大小 1x ~ 2x 目标码率 太小易跳帧,太大失去 CBR 意义
-maxrate 最大瞬时码率 等于或略高于目标码率 直播场景建议等于目标码率
-nal-hrd cbr 启用严格 CBR 必须添加 不加则不是严格 CBR

CBR 的优缺点总结

说了这么多,我们来总结一下 CBR 的优缺点。

优点:

  • 码率恒定,适合固定带宽的传输通道
  • 便于估算存储空间和带宽需求
  • 兼容性好,老旧设备也能稳定处理

缺点:

  • 画质波动大,复杂场景质量下降明显
  • 填充比特浪费带宽
  • 跳帧影响流畅度

一句话总结:CBR 是「牺牲质量换稳定」的码率控制模式。适合直播、视频会议等带宽固定的场景,不适合对画质要求高的离线编码。

CBR 核心逻辑流程图

下面这张图展示了 CBR 编码器的工作流程,从输入帧到输出码流的完整路径:

CBR 编码器工作流程 CBR 编码器工作流程 输入视频帧 H.264/H.265 编码 码率检测 当前码率 vs 目标码率 填充比特 (Padding) 正常输出 跳帧 (Frame Skip) 输出恒定码率流 填充比特:码率不足时补充无意义数据 跳帧:码率超标时丢弃帧以降低码率

从流程图可以看出,CBR 编码器在码率检测后有三个分支。码率正常就直接输出,码率过低就填充比特,码率过高就跳帧。这就是 CBR 保持码率恒定的全部秘密。

避坑提醒:我曾经在一个直播项目中,把 -bufsize 设得特别小,想追求码率的绝对恒定。结果画面稍微复杂一点就开始跳帧,观众反馈「卡成 PPT」。后来我把 -bufsize 调到目标码率的 1.5 倍,跳帧问题就解决了。记住,CBR 不是越严格越好,要给编码器留一点缓冲空间。