preset 是「速度换效率」的档位,不是「压缩质量」的档位:ultrafast 的字节是 medium 的 3.6 倍。 profile 决定兼容性,baseline 要付将近一倍的体积。
前面几节调的是码率、帧率、GOP 这些「结果参数」。 这一节调的是编码器本身的「做事方式」——同样的目标,不同的走法。
一、preset:五个档位的实测
同一段素材、同一档 CRF 26,只换 preset:
preset 字节 相对 medium
ultrafast 16817 3.58× veryfast 4342 0.92× medium 4696 1.00× slow 4690 1.00× veryslow 4793 1.02×
第一行字节是 medium 的 3.6 倍——ultrafast 关掉了太多工具,代价是体积暴涨。 它换来的速度也确实快:耗时大约只有 medium 的一半。
但越往慢走,字节并没有越来越小:slow 与 medium 就差 6 字节,veryslow 反而略大。 因为这段素材太好压,x264 那些「更聪明的决策」没有发挥空间,只在耗时上体现出来了。
所以 preset 的正确用法是:先选能接受的最慢一档,再用实测数字决定要不要更慢。 照「越慢越小」这句话盲目加档,往往只多花时间。
二、tune:三个场景的实测
tune 是「告诉编码器这段素材是什么类型」:
tune 字节 相对 film
film 4796 1.00× animation 4780 1.00× zerolatency 6637 1.38×
film 与 animation 的差别几乎没有,因为这段素材既不是实拍也不是动画,它就是个合成图案。 tune 只在素材特征明显时才起作用,选错了不会有灾难,但也不会有效果。
zerolatency 那一行明显更大,因为它把 B 帧与前瞻都关了—— 换来的是「编完立刻能发」,不用等后面几帧。直播、视频会议用的就是这一档。
三、profile:兼容性的真实价格
三档 profile,同一档 CRF:
profile 字节 相对 high
baseline 9103 1.94× main 4764 1.01× high 4696 1.00×
baseline 是 high 的 1.94 倍——它不支持 CABAC 熵编码,也不支持 B 帧。 这就是「兼容老设备」的真实价格:同样的画质,字节几乎翻倍。
main 与 high 差 1%,因为这段素材上 high 的那些工具也没派上用场。 所以真正要付钱的只有 baseline 那一档。
今天除非要喂给十年前的播放器,否则不该主动降到 baseline。 手机、浏览器、智能电视都认 high。
四、动手 Demo:preset、tune、profile 各扫一遍
先按 medium 编一遍当基准,再换四个 preset 比字节。 然后各试三个 tune、三个 profile,看哪一档真的改变了体积。
import av, os, time
def enc(dst, opts):
c1 = av.open(dst, u"w")
s1 = c1.add_stream(u"libx264", rate=25)
s1.width, s1.height, s1.pix_fmt = 160, 90, u"yuv420p"
s1.options = opts
c0 = av.open(u"s5.mp4")
t0 = time.time()
for f in c0.decode(video=0):
for o in s1.encode(f.reformat(width=160, height=90, format=u"yuv420p")):
c1.mux(o)
for o in s1.encode(None):
c1.mux(o)
c1.close()
c0.close()
return os.path.getsize(dst), time.time() - t0
base = enc(u"p_medium.mp4", {u"crf": u"26", u"preset": u"medium"})
print(u"medium %d 字节 %.3f 秒" % base)
for p in (u"ultrafast", u"veryfast", u"slow", u"veryslow"):
n, t = enc(u"p_%s.mp4" % p, {u"crf": u"26", u"preset": p})
print(u"%-10s %d 字节 %.3f 秒 字节是 medium 的 %.2f 倍"
% (p, n, t, n / float(base[0])))
for tn in (u"film", u"animation", u"zerolatency"):
n, t = enc(u"t_%s.mp4" % tn, {u"crf": u"26", u"tune": tn})
print(u"tune %-12s %d 字节" % (tn, n))
hi = enc(u"pr_high.mp4", {u"crf": u"26", u"profile": u"high"})
print(u"profile high %d 字节" % hi[0])
for pf in (u"baseline", u"main"):
n, t = enc(u"pr_%s.mp4" % pf, {u"crf": u"26", u"profile": pf})
print(u"profile %-8s %d 字节 是 high 的 %.2f 倍" % (pf, n, n / float(hi[0])))
实跑输出:
--------------------------------------------------------------------
5.7.1 FFmpeg 中 libx264 的选项——preset 与 tune 到底改了什么
--------------------------------------------------------------------
**① preset:五个档位各编一遍**
preset 字节 耗时 相对 medium
-------------------------------------------------
ultrafast 22165 0.018 秒 4.30×
veryfast 4726 0.023 秒 0.92×
medium 5150 0.044 秒 1.00×
slow 5078 0.042 秒 0.99×
veryslow 5243 0.083 秒 1.02×
**第一行字节是 medium 的 4.3 倍——ultrafast 关掉了太多工具,代价是体积暴涨。**
**但越往慢走,字节并没有越来越小:slow 比 medium 还小一点,veryslow 反而略大。**
**因为这段素材太好压,x264 那些「更聪明的决策」没有发挥空间,只在耗时上体现出来了。**
**所以 preset 的正确用法是:先选能接受的最慢一档,再用实测数字决定要不要更慢。**
**② tune:三个场景各编一遍**
tune 字节 耗时
----------------------------------
film 5243 0.039 秒
animation 5291 0.042 秒
zerolatency 7939 0.043 秒
**zerolatency 那一行明显更大,因为它把 B 帧与前瞻都关了——**
**换来的是「编完立刻能发」,不用等后面几帧。直播、视频会议用的就是这一档。**
**③ profile:兼容性是有代价的**
profile 字节 相对 high
---------------------------------
baseline 10325 2.00×
main 5241 1.02×
high 5150 1.00×
**baseline 是 high 的 2.0 倍——它不支持 CABAC 熵编码,也不支持 B 帧。**
**这就是「兼容老设备」的真实价格:同样的画质,字节翻倍。**
**今天除非要喂给十年前的播放器,否则不该主动降到 baseline。**
耗时这一列每次跑都会变,量级才可靠;字节是稳定的。 所以判断「要不要更慢」时该看字节,不该看自己这台机器这一次的秒数。
preset、tune、profile 都是 x264 的选项,直接写进 s1.options。
它们的值都是名字字符串,不用加引号也不用减号。
写错名字不会报错,x264 只会在日志里提一句「未识别的参数」, 然后照默认值跑完——所以看到 result 不对时,先回来看拼写。
30 秒实验
- 命令行对照:
ffmpeg -i 源.mp4 -c:v libx264 -preset slow -crf 26 出.mp4。 - 量到底:写脚本把 9 个 preset 全扫一遍,画一张「字节 vs 耗时」的曲线。
- 给老设备:
-profile:v baseline -level 3.0,同时记下体积涨了多少。
常见误区
- 以为 preset 越慢体积一定越小。这段素材上 veryslow 反而比 medium 大。
- 把 preset 当质量参数。它是速度与效率的取舍,改质量要用 CRF。
- 随手降到 baseline。体积几乎翻倍,而且今天已经没必要。
自测三问(点开对答案)
1. preset 改的是什么? —— 编码器愿意花多少算力去找更优的编码决策。ultrafast 关掉大量工具,字节涨到 3.6 倍。 2. 为什么 slow 与 medium 差不了几个字节? —— 素材太简单,更聪明的决策没有发挥空间,只在耗时上体现。 3. baseline 为什么贵? —— 它不支持 CABAC 熵编码与 B 帧,同样的画质要多花将近一倍字节。- ☐ (本节完,下一节 5.7.2 x264.exe 中的选项名与选项值)