这一代换得不划算:同样 CRF,x265 的字节是 x264 的 127%,耗时还要多两三倍。 HEVC 的收益要靠大块划分与大分辨率,小画面上摊不开。
x264 用了二十多年,x265 是它的下一代。 「新一代更省」这句话在这个尺寸上不成立,这一节用实测把这件事讲清楚。
一、同 CRF 下两代对比
同一段素材、同一档 CRF 26:
编码器 字节 相对 x264
libx264 4696 1.00× libx265 5941 1.27×
这一组数字是反直觉的:x265 的字节是 x264 的 127%,耗时还要多两三倍。 也就是说在这个尺寸上,HEVC 既没省下空间,还多花了时间。
原因有两层:一是 HEVC 的收益来自大块划分与更多参考帧,160×90 这点像素摊不开; 二是 CRF 在两代编码器里不是同一把尺子,同数值也不等于同画质。
换 HEVC 的正确姿势是:在真实的素材与分辨率上测一遍,而不是照「新一代更省」这句话走。 在 1080p 与 4K 上,x265 通常能省三到五成——但那是另一组实验。
二、x265 挑像素格式
同样给 libx265,两种像素格式的结果不同:
像素格式 libx265 的结果
yuv420p 成功,5941 字节 nv12 被拒(returned 22)
nv12 其实就是「半平面」的 yuv420p:亮度一整块,色度交错成一整块。 两者数据量一样,只是排法不同;x265 只认 yuv420p,转一下格式就能过。
反过来,硬件编码器普遍偏爱 nv12——这一点在 5.9 会看到实例: qsv 给 yuv420p 直接拒绝,给 nv12 才成功。
所以「同一个 yuv420p 家族」内部还要再分一次排法,这是转码里常被忽略的一层开销。 多一次格式转换,就多一次全帧遍历。
三、该不该换 HEVC
按场合决定,不按「新不新」决定:
场合 建议
网页、要最大兼容 用 H.264 4K、存储吃紧 用 H.265 要硬件解码保底 先查设备支持 老手机、老电视 别用
第三行是实际操作里最该先做的一步:HEVC 的专利池比 H.264 更麻烦, 不少设备厂商干脆不解码,用户看到的就是黑屏。
所以「省了多少字节」永远不能单独当决策依据,得先确认播放端认不认。 这一条在 5.4.2 讲 FLV 时说过一次,换 HEVC 时同样成立。
四、动手 Demo:两个编码器各编一遍,再换像素格式试一次
同一档 CRF 26,分别用 libx264 与 libx265 编一遍,比字节与耗时。 再给 libx265 换成 nv12 像素格式,看它接不接。
import av, os, time
def enc(dst, codec, pix=u"yuv420p", opts=None):
c1 = av.open(dst, u"w")
s1 = c1.add_stream(codec, rate=25)
s1.width, s1.height, s1.pix_fmt = 160, 90, pix
if opts:
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=pix)):
c1.mux(o)
for o in s1.encode(None):
c1.mux(o)
c1.close()
c0.close()
return os.path.getsize(dst), time.time() - t0
x4 = enc(u"c264.mp4", u"libx264", opts={u"crf": u"26"})
x5 = enc(u"c265.mp4", u"libx265", opts={u"crf": u"26"})
print(u"libx264 %d 字节 %.3f 秒" % x4)
print(u"libx265 %d 字节 %.3f 秒 是 x264 的 %.0f%%"
% (x5[0], x5[1], x5[0] * 100.0 / x4[0]))
for pix in (u"yuv420p", u"nv12"):
try:
n = enc(u"px_%s.mp4" % pix, u"libx265", pix, {u"crf": u"26"})
print(u"%-8s 成功 %d 字节" % (pix, n[0]))
except Exception as e:
print(u"%-8s 被拒 %s" % (pix, str(e)[:45]))
实跑输出:
--------------------------------------------------------------------
5.8 libx265 的常用编码选项及应用案例
--------------------------------------------------------------------
**① 同 CRF 下 libx264 与 libx265 对比**
编码器 字节 耗时
------------------------------
libx264 4696 0.039 秒
libx265 5941 0.119 秒
**这一组数字是反直觉的:x265 的字节是 x264 的 127%,耗时却是 3.0 倍。**
**也就是说在这个尺寸上,HEVC 既没省下空间,还多花了时间。**
**原因是 HEVC 的收益来自「大块划分与更多参考帧」,160×90 这点像素根本摊不开它那些工具;**
**再加上 CRF 在两代编码器里不是同一把尺子,同数值也不等于同画质。**
**换 HEVC 的正确姿势是:在【真实的】素材与分辨率上测一遍,而不是照着「新一代更省」这句话走。**
**② x265 挑像素格式,nv12 会被拒**
像素格式 libx265 的结果
---------------------------------
yuv420p 成功
nv12 被拒(returned 22)
**nv12 其实就是「半平面」的 yuv420p:亮度一整块,色度交错成一整块。**
**两者数据量一样,只是排法不同;x265 只认 yuv420p,转一下格式就能过。**
**反过来,硬件编码器普遍偏爱 nv12——显卡处理交错排列更省事,这也是一处常见的转格式开销。**
**③ 该不该换 HEVC**
场合 建议
----------------------------------
网页、要最大兼容 用 H.264
4K、存储吃紧 用 H.265
要硬件解码保底 先查设备支持
老手机、老电视 别用
**第三行是实际操作里最该先做的一步:HEVC 的专利池比 H.264 更麻烦,**
**不少设备厂商干脆不解码,用户看到的就是黑屏。**
libx265 必须给 crf,不给会报 returned 22。
它不像 libx264 有默认值兜着,这一条很容易忘。
x265 会在 stderr 打一大段 [info] 日志,那是它自己的统计报告。
用 PyAV 时这些日志走的是 C 层的输出,不影响结果。
比两代编码器时,crf 只当「大致同档」看,不能当「同画质」。
真要公平比较得先做主观或客观画质评估,那是另一门功课。
30 秒实验
- 命令行对照:
ffmpeg -i 源.mp4 -c:v libx265 -crf 26 出.mp4。 - 换容器:x265 常配
-tag:v hvc1才能在苹果设备上播。 - 大分辨率再试:把素材放大到 1280×720,两代的差距会明显变大。
常见误区
- 以为新一代一定更省。小画面上 x265 反而更大,而且慢三倍。
- 忘了给
crf。libx265 没有默认值,报的是含义含糊的returned 22。 - 给 libx265 传 nv12。它只认 yuv420p,得先转格式。
自测三问(点开对答案)
1. 为什么 x265 在这个尺寸上不省? —— HEVC 的收益来自大块划分与更多参考帧,160×90 这点像素摊不开它的工具。 2. libx265 对像素格式有什么要求? —— 只认 yuv420p,nv12 会被拒。硬件编码器正相反,偏爱 nv12。 3. 什么时候该用 HEVC? —— 4K、存储吃紧、且播放端确认支持。网页交付仍该用 H.264。- ☐ (本节完,下一节 5.9 FFmpeg 的 GPU 硬件加速原理及应用案例)