分辨率和码率是两个独立的旋钮,很多人当成一个。 分辨率决定「细节上限」,码率决定「这点细节保得住多少」。
上一节只用了默认质量。这一节把两个旋钮分别拧一遍,各自量出影响。 PSNR 的定义在 26 课,这里只把它当「客观画质分」用。
一、两个旋钮各管什么
| 旋钮 | 影响 | 典型取值 |
|---|---|---|
| 分辨率 | 细节上限 | 1920×1080、1280×720 |
| 码率/质量 | 这个细节保得住多少 | CRF 18~28 |
举个不精确但好记的比方:分辨率是「画布多大」,码率是「颜料给多少」。 画布大而颜料少,就是一片糊;画布小而颜料多,就是清晰但只能看一小块。 两者不能互相替代——720p 配高码率永远不会变成 1080p。
二、只拧质量:CRF 台阶
CRF 是「恒定质量」模式:编码器自己决定用多少字节,你只负责说「要多清楚」。 数值越小越清楚,18 到 28 是常用区间。
| CRF | 文件大小 | 码率 | PSNR |
|---|---|---|---|
| 18 | 12.4 KB | 102 kbps | 46.9 dB |
| 23 | 10.4 KB | 85 kbps | 42.2 dB |
| 28 | 8.3 KB | 68 kbps | 38.8 dB |
| 35 | 6.4 KB | 52 kbps | 32.7 dB |
CRF 每降 5 档,文件涨两三成,PSNR 涨三到四 dB。这是台阶, 不是线性——因为 CRF 本身就是量化步长的对数值。
PSNR 怎么读:40 dB 以上肉眼基本看不出差别;35 dB 左右能看出轻微模糊; 30 dB 以下就开始糊了。 这个门槛是经验值,不同内容差别很大——但用来判断「还能不能降」够用。
三、只拧分辨率:像素减半,文件也减半
把源缩到不同尺寸再编,质量参数不动:
| 分辨率 | 帧字节 | 编码后 | 码率 |
|---|---|---|---|
| 320×240 | 115200 | 10.4 KB | 85 kbps |
| 240×180 | 64800 | 7.5 KB | 62 kbps |
| 160×120 | 28800 | 5.1 KB | 42 kbps |
像素少一半,文件大约少一半,因为细节总量就少一半,能压的也就少一半。 注意它比 CRF 的杠杆更硬:CRF 降 5 档只省两三成,分辨率砍一半直接省三成多, 而且编码耗时会跟着掉(像素少了,搜索也少了)。 所以「带宽不够」时,先降分辨率往往比降质量划算。
四、命令行怎么写
| 想要 | 参数 | 注意 |
|---|---|---|
| 恒定质量 | -crf 23 |
文件大小不可控 |
| 恒定码率 | -b:v 1000k |
复杂画面会糊 |
| 限峰值 | -maxrate 1500k -bufsize 3000k |
两个要给,只给一个没用 |
| 改尺寸 | -vf scale=640:480 |
必须偶数,否则编码报错 |
-crf 和 -b:v 同时给时,-crf 优先——x264 会进 CRF 模式,把 -b:v 当上限参考。
想测码率就只给 -b:v。
-vf scale 的宽高必须是偶数,因为 yuv420p 两个色度平面各是宽高的一半,奇数除不尽。
报错信息是「width not divisible by 2」,看到就知道是这个。
五、动手 Demo:码率和分辨率,两个旋钮各管什么
Demo 分两段:先只拧 CRF(18/23/28/35),再只拧分辨率(320/240/160)。 PSNR 是解回来跟源逐像素比出来的,不是查表。
def enc(crf=None, w=320, h=240):
c = av.open("t.h264", "w", format="h264")
s = c.add_stream("libx264", rate=30)
s.width, s.height, s.pix_fmt = w, h, "yuv420p"
if crf is not None:
s.options = {"crf": str(crf)}
else:
s.bit_rate = 400000 # 恒定码率
...
def psnr(a, b):
mse = ((a.astype("f8") - b.astype("f8")) ** 2).mean()
return 10 * math.log10(255.0 ** 2 / mse)
实跑输出:
--------------------------------------------------------------------
码率和分辨率,两个旋钮各管什么
--------------------------------------------------------------------
**分辨率和码率是两个独立的旋钮,很多人以为是一个。**
旋钮 影响 典型取值
-------------------------------------------------------------
分辨率 细节上限 1920×1080、1280×720
码率/质量 这个细节保得住多少 CRF 18~28
**先用同一份源,只拧「质量」这个旋钮(CRF 越小质量越高):**
CRF 文件大小 码率 PSNR
---------------------------------------------
18 12.4 KB 102 kbps 46.9 dB
23 10.4 KB 85 kbps 42.2 dB
28 8.3 KB 68 kbps 38.8 dB
35 6.4 KB 52 kbps 32.7 dB
**CRF 每降 5 档,文件涨两三成**,PSNR 涨 3 到 4 dB。这就是 x264 的「质量台阶」,不是线性的。
**PSNR 到 40 dB 以上,肉眼基本看不出差别**;35 dB 左右能看出轻微模糊;**30 dB 以下就开始糊了**。
**再拧分辨率这个旋钮**(把源缩到不同尺寸再编,质量参数不变):
分辨率 帧字节 编码后 码率
----------------------------------------------
320×240 115200 10.4 KB 85 kbps
240×180 64800 7.5 KB 62 kbps
160×120 28800 5.1 KB 42 kbps
**像素少一半,文件大约少一半**——因为细节总量就少一半。
**这两个旋钮的组合决定画质**:1080p 配低码率会糊,720p 配高码率不会变回 1080p。
**所以「想要清楚」的第一件事是提分辨率,第二件才是提码率。**
PSNR 公式里那个 255 是 8 位像素的最大值,换成 10 位就是 1023。 这个数写错,PSNR 会差 12 dB,很容易看出来,但也容易糊过去。 分辨率那一段是把源先缩再编, 所以「帧字节」那一列也跟着变了——这是缩放带来的,不是编码器带来的,两者要分清。
30 秒实验
- 把 CRF 设成 51(最大),看 PSNR 掉到多少,还认不认得出画面。
- 用
-b:v 85k复现第一张表的 85 kbps 那一行, 看 PSNR 差多少——这就是恒定码率和恒定质量的差别。 - 把
scale的宽改成 641,看报错原文。
常见误区
- 以为高码率能补回分辨率。 720p 编得再清楚也不是 1080p, 分辨率是细节上限,码率只能决定保住多少。
- 以为 CRF 和码率是同一件事的两种写法。 CRF 是「按质量给字节」,码率是「按字节给质量」, 方向正好相反。
- 以为 PSNR 高就一定好看。 PSNR 是逐像素平均差, 对「整体偏色」不敏感,对「局部糊」也不敏感,只能当参考。
自测三问(点开对答案)
1. 为什么 CRF 每降 5 档文件只涨两三成,而不是翻倍? —— CRF 是量化步长的对数值,降 5 档是把步长减半, 而码率和步长不是线性关系——**大部分比特花在少数难编的块上**。 2. 带宽不够时,先降分辨率还是先降码率? —— 先降分辨率。**它省得更多(像素减半文件减半),而且编码更快**;降码率会把所有细节一起糊掉。 3. `-crf` 和 `-b:v` 同时给会怎样? —— `-crf` 优先,进 CRF 模式,`-b:v` 退化成参考上限。**想测恒定码率就只给 `-b:v`。**下一节拧第三个旋钮:多久给一次完整画面(GOP)。
- ☐ (本节完,下一节 04.01.03 控制视频的GOP)