557 个编解码器里,只有 211 个能编,占 38%。 这个比例说明一件事:解比编容易得多。
3.11.4 讲输入侧,这一节开始讲「谁把画面压成码流」。 编码器这一侧的坑集中在「表里有但跑不起来」,下一段专门讲。
一、211 是怎么数出来的
编解码器混在一张表里,靠能力把它拆开:
能力 数量 说明
只能编 27 如部分硬件编码器 能编也能解 184 如 mpeg4、aac 编码器合计 211 就是 -encoders 的行数 编解码器总数 557 就是 -codecs 的行数
能编的只占 38%,这个比例很能说明问题: 解比编容易得多——只要能读懂别人的格式,不需要自己产出合规的码流。
而且「能编」的门槛还带着合规要求:编出来的码流要能被别的解码器认。 这一条把一大批「理论上能写」的格式挡在了门外。
二、名字形态能看出它从哪来
不用查文档,看名字前缀就能猜出它的来源:
名字形态 来自哪 例子
lib 开头 外挂第三方库 libx264/libx265 纯字母 FFmpeg 自研 mpeg4/mpeg2video 带 _mf 后缀 调系统媒体框架 h264_mf/aac_mf 带 _qsv/_nvenc 调硬件 h264_qsv/h264_nvenc
这个区别很实际:外挂和硬件的要额外装依赖,自研的那一批「装了就有」。 自研的画质通常不如 libx264,但胜在到处都能跑。
第四行要特别注意:看到 _qsv、_nvenc 这些后缀,说明它要特定显卡。
在没有对应硬件的机器上,这条一定跑不起来——不是参数写错。
三、表里有,不等于跑得起来
ffmpeg -encoders | grep x264 只能证明它在表里,不能证明它能跑。
真正确认要编一帧试试:
ffmpeg -f lavfi -i testsrc -frames:v 1 -c:v libx264 out.mp4
现象 原因 怎么确认
列表里有,一编就报错 运行时找不到动态库 看报错里的库名 列表里没有 编译时没带这个库 换一份构建 能编但参数不认 版本不同,选项变了 -h encoder=名字
第一行是 Windows 上最常见的一种:库里编进去了,但 .dll 没跟着放。
报错里会直接写缺哪个文件,照着补上就行,跟参数无关。
所以「装完先编一帧」这个动作要成为习惯,比看清单可靠得多。 清单是静态的,编一帧是真的走了一遍完整流程。
四、动手 Demo:557 个里 211 个能编
把编解码器表按能力拆开数一遍,再看一个具体编码器的几个关键属性。 重点在最后两行:它同时声明「支持无损」和「通常有损」,这看着矛盾,其实不矛盾。
import av
both, enconly = 0, 0
for n in av.codecs_available:
try:
w = av.codec.Codec(n, u"w")
except Exception:
continue
if not w.is_encoder:
continue
try:
r = av.codec.Codec(n, u"r")
except Exception:
enconly += 1
continue
if r.is_decoder:
both += 1
else:
enconly += 1
print(u"编解码器总数 %d" % len(av.codecs_available))
print(u"能编也能解 %d" % both)
print(u"只能编 %d" % enconly)
print(u"编码器合计 %d" % (both + enconly))
c = av.codec.Codec(u"libx264", u"w")
print(u"无损模式 %s" % c.lossless)
print(u"通常有损 %s" % c.lossy)
实跑输出:
--------------------------------------------------------------------
3.11.5 -encoders——557 个里 211 个能编
--------------------------------------------------------------------
**① 编解码器混在一张表里,靠 is_encoder 分**
能力 数量 说明
---------------------------------------------------
只能编 27 如部分硬件编码器
能编也能解 184 如 mpeg4、aac
编码器合计 211 就是 -encoders 的行数
编解码器总数 557 就是 -codecs 的行数
**能编的只占 38%,这个比例很能说明问题:**
**解比编容易得多——只要能读懂别人的格式,不需要自己产出合规的码流。**
**② 外挂编码器与内置编码器,名字上看不出来**
名字形态 来自哪 例子
---------------------------------------------------------------
lib 开头 外挂第三方库 libx264/libx265
纯字母 FFmpeg 自研 mpeg4/mpeg2video
带 _mf 后缀 调系统媒体框架 h264_mf/aac_mf
带 _qsv/_nvenc 调硬件 h264_qsv/h264_nvenc
**第二行与第三四行的区别很实际:外挂和硬件的要额外装依赖,**
**自研的那一批编出来的画质通常不如 libx264,但胜在「装了就有」。**
**③ 怎么确认某个编码器真的能用**
**`ffmpeg -encoders | grep x264` 只能证明它在表里,不能证明它能跑。**
**真正确认要编一帧试试——`ffmpeg -f lavfi -i testsrc -frames:v 1 -c:v libx264 out.mp4`。**
**这一步失败的原因通常是:库里编进去了,但运行时的动态库找不到。**
**④ 本机能编的一个具体例子**
项 值
------------------------------------------------------------------------
名字 libx264
完整名 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
支持无损模式? True
通常是有损? True
**最后两行同时为 True 不矛盾:libx264 既能无损也能有损。**
**无损模式要显式指定(`-qp 0`),默认走的是有损路径。**
**所以「libx264 会不会掉画质」这个问题,答案是「看你怎么调」,不是「一定掉」。**
第三行那个「编码器合计」就是 -encoders 的行数,占总数不到四成。
这个比例在各家解码库上都差不多,不是这一份构建的特例。
最后两行同时为 True,这不是数据错:libx264 既能无损也能有损。
无损要显式指定(-qp 0),默认走的是有损路径。
所以「libx264 会不会掉画质」这个问题,答案是「看你怎么调」,不是「一定掉」。
这一段用「能不能用 r 方向打开」来判它能不能解,是一种近似。
严格说 is_decoder 才是准的;这里两个都判了,所以两种构建上都不会数错。
30 秒实验
- 数能编的:
ffmpeg -encoders | wc -l,与-codecs的行数对比。 - 真编一帧:
ffmpeg -f lavfi -i testsrc -frames:v 1 -c:v libx264 out.mp4,比看清单可靠。 - 查它的参数:
ffmpeg -h encoder=libx264,看-preset与-crf的范围。
常见误区
- 以为
-encoders里有就能用。动态库缺失时列表里有、一编就报错,要真编一帧验证。 - 把
lossless=True当成「libx264 无损」。它只是「支持无损模式」,默认路径是有损的。 - 以为「能编」的门槛和「能解」一样。编出来的码流要合规,比读懂别人难得多。
自测三问(点开对答案)
1. 为什么能编的编码器只有能解的三分之一左右? —— 因为解码只需读懂别人的码流,而编码要产出符合规范的码流,合规门槛高得多。 2. `libx264` 的 `lossless` 与 `lossy` 同时为 True,怎么理解? —— 它两种模式都支持:默认走有损,要无损得显式指定 `-qp 0`,两者并不矛盾。 3. 列表里有 libx264,一编就报错,最可能是什么原因? —— 运行时找不到对应的动态库(Windows 上缺 dll),报错里通常会直接写出缺哪个文件。- ☐ (本节完,下一节 3.11.6 -decoders)