halfsize / 画质
「不损画质」到底损的是什么
「压缩视频但不损画质」这句话里,其实藏着三种不同的需求。一种免费但省不下体积,一种诚实但会让文件变大, 还有一种是大多数人真正想要的。没人明说的一点是:画质和体积是同一个旋钮。
三种说法,三种结果
| 你的说法 | 实际做的事 | 体积 | 画质 |
|---|---|---|---|
| 「只换个格式」 | 流拷贝,不重编码 | 基本不变,±1% | 像素完全一致 |
| 「无损」 | x264 加 -qp 0 | 大 2–5 倍 | 像素完全一致 |
| 「视觉无损」 | 原分辨率下 CRF 18–20 | 原片的 40–60% | VMAF 通常 95+,肉眼一致 |
| 「压到装得下」 | 指定体积,两遍编码,逐档降分辨率 | 正好是你要的数字 | 实测并打印,典型 82–89 |
没有第四行,能让文件小很多而像素不变。压缩就是丢信息,唯一的问题是:丢掉的这部分你原本会不会注意到。
同一个源片的实测数字
60 秒 1080p30、18 Mbps(136 MB),本地编码后和原片对比。指定大小的几行是实测;CRF 那行是常见范围,不是单次测试:
| 方式 | 输出 | 分辨率 | VMAF | 结论 |
|---|---|---|---|---|
| 原片 | 136 MB | 1920×1080 | 100 | 基准 |
| CRF 18,不降分辨率 | 原片的 40–60% | 1920×1080 | 通常 95+ | 视觉无损 |
| 压到 20 MB | 19.45 MB | 1280×720 | 88.3 | 轻微变软 |
| 压到 10 MB | 9.77 MB | 960×540 | 82.9 | 变软,运动拖影 |
| 压到 5 MB | 4.93 MB | 640×360 | 72.0 | 明显损失 |
真正值得看的是代价曲线,而不是某一行。20 MB 减半到 10 MB,大约掉 5 个 VMAF;再从 10 MB 减半到 5 MB, 又要掉 11 个。第一次减半是划算的交易,第二次就开始「看得出变差」了。反过来加码率也一样:最后那几分,非常贵。
为什么 CRF 和「20 MB 以内」是两个问题
CRF 问的是「每帧我可以丢掉多少」,丢完多大就是多大。指定体积问的是「我每秒有多少字节」, 画质掉到哪就是哪。如果卡你的是报名表、邮箱或聊天软件,只有第二个问题有用, 再怎么调 CRF 也给不出体积保证。
体积在底层会换算成码率:字节 × 8 ÷ 秒 − 音频 − 封装开销,然后再挑一个能扛住这个码率的分辨率,
H.264 的经验值是每像素 0.072 bit(H.265 是 0.045)。这就是为什么 1080p 给 500 kbps 会糊,
而 540p 给 500 kbps 还看得过去。
画质到底花在哪
- 分辨率——最先该花的地方。干净的小画面胜过发软的大画面。
- 运动——横摇、彩带、水面、手持抖动,吃码率比人脸快得多。
- 颗粒和噪点——胶片颗粒接近随机噪声,编码器得实打实地花比特。编码前做轻微降噪, 同样体积下能换回好几分 VMAF。
- 音频——128 kbps 大约每分钟 1 MB。去掉它,等于把体积全留给画面。
诚实的检查方法:VMAF 是整帧打分,颗粒损失很容易被平均值掩盖。用最终观看的那块屏幕, 100% 放大看 10 秒。你在那里看不出差别,别人也看不出。
命令
# 画质优先,多大就多大
$ npx halfsize 片段.mp4 --crf 19 --no-downscale
# 硬性上限,事后报告画质
$ npx halfsize 片段.mp4 --to 20mb
# 同样上限,但保住画面尺寸
$ npx halfsize 片段.mp4 --to 20mb --no-downscale
第一行对应的 FFmpeg 是 -crf 19 -preset slow;第二行对应的是先算码率再跑两遍,
也就是工具替你自动化的部分。想自己写命令,看 ffmpeg 指定大小那篇。
上限实在太小的时候
一小时的课程塞进 20 MB,那是 44 kbps,没有救。真正有用的做法按伤害从小到大排: 剪成关键的那几分钟;去掉音频、课件另发;或者接受 360p。再压第四遍不会有任何改善。
常见问题
有没有真正零损失的压缩?
只有不重编码才行。流拷贝像素不变,但省不下体积;无损编码像素精确,却比原片大好几倍。比原片小的文件,按定义都有损。
VMAF 多少算视觉无损?
93 以上,正常距离看不出。90–93 要并排对比。85 以下运动和小纹理就开始发软。
用 CRF 还是指定大小?
不在意体积就用 CRF;有平台卡体积就只能指定大小,只有后者带保证。
降分辨率比降码率更伤吗?
通常更好。同样码率下,清晰的 540p 比带块的 1080p 观感更干净。
压完还能救回来吗?
不能。对有损文件再编码,只会在损失上叠加损失。拿到满意输出之前,保留原片。