-formats 打的是这份构建能读能写的容器格式清单,一共 414 个。 每个前面带字母标记:d 能读、e 能写、de 两样都行。
3.10 讲的是「怎么查」,从这一节开始逐个查那批清单。 六节各查一类:格式、封装、解封装、设备、编码器、解码器。
一、两列字母决定这个格式能干什么
清单里每行形如 DE mp4 MP4 (MPEG-4 Part 14),开头那两个字母是能力标记:
标记 含义 带这个标记的格式数
d demuxing,能读(解封装) 368 e muxing,能写(封装) 182 de 两样都能 136
第一二行加起来不等于 414,因为「读写都行」那 136 个在两个标记里各算了一次。
所以 -demuxers 的行数是 368、-muxers 是 182,交集就是那 136。
这个「交集被重复计数」的特点是理解三张表关系的关键:
-formats 是全集,另外两张是它的两个方向上的切片。
二、按能力分成三类,看总数怎么凑出来
把 414 拆开,三类各占多少一目了然:
能力 格式数 标记 典型例子
只能读 232 d 各种老采集格式 只能写 46 e 输出专用的封装 读写都行 136 de mp4、mkv、flv、ts 合计 414 — 就是 -formats 的行数
「只能读」的那 232 个多是老格式:能解出来给人看,没人再往里写新内容。 「只能写」的 46 个多是输出专用:运行时才生成,不代表是一个磁盘上的文件。
这个分布和 3.11.3、3.11.5 那两节讲的「读多写少」是同一件事的两个侧面。 记住这条规律,以后见到「这个格式怎么不能输出」时就不会意外了。
三、这个数为什么会随构建变
-formats 打的是「编译进这份 libavformat 的东西」,不是「FFmpeg 理论上支持的」。
所以官方完整版、系统包管理器版、自己编的版本,三个数可以完全不同。
版本来源 格式数大概 差别在哪
官方完整构建 最多 外挂库都编进去了 发行版仓库版 中等 按许可证剔掉一部分 自己编的精简版 最少 只要用到的那些
这就解释了 1.1.2 那个现象:同一段命令在别人机器上能跑,在你这里报找不到格式。 不是命令错了,是你这份构建里没有那个组件。
所以「查清单」这件事要养成两个习惯:查自己机器上的,别信网上截图里的数字。 以及,拿到一份别人写的脚本时,先看它依赖的格式在不在。
四、动手 Demo:414 个格式,按读写能力分三类
沙箱里没有 ffmpeg.exe,-formats 打不出来。
但这张表的内容来自 libavformat 注册的组件清单,库这一层能遍历同一批组件。
这一段把「能读多少、能写多少、都能多少」三个数数出来。
import av
names = sorted(av.formats_available)
inn, out, both = [], [], []
for n in names:
try:
r = av.format.ContainerFormat(n)
except Exception:
continue
if r.is_input and r.is_output:
both.append(n)
elif r.is_input:
inn.append(n)
else:
out.append(n)
print(u"格式总数 %d" % len(names))
print(u"只能读 %d" % len(inn))
print(u"只能写 %d" % len(out))
print(u"读写都行 %d" % len(both))
print(u"d 标记合计 %d" % (len(inn) + len(both)))
print(u"e 标记合计 %d" % (len(out) + len(both)))
实跑输出:
--------------------------------------------------------------------
3.11.1 -formats——414 个格式,按读写能力分三类
--------------------------------------------------------------------
**① 两列字母 D 和 E,决定这个格式能干什么**
标记 含义 带这个标记的格式数
------------------------------------------------------------
d demuxing,能读(解封装) 368
e muxing,能写(封装) 182
de 两样都能 136
**注意第一二行加起来不等于 414:因为「读写都行」那 136 个在两个标记里都算了一次。**
**所以 `-demuxers` 的行数是 368,`-muxers` 是 182,两者的交集就是那 136 行。**
能力 格式数 标记 典型例子
---------------------------------------------------------
只能读 232 d 各种老采集格式
只能写 46 e 输出专用的封装
读写都行 136 de mp4、mkv、flv、ts
合计 414 — 就是 -formats 的行数
**只能读的多是老格式:能解出来但没人再往里写。**
**只能写的多是输出专用:运行时生成,不代表是一个「文件」。**
**② 这个数为什么会随构建变**
**`-formats` 打的是「编译进这份 libavformat 的东西」,不是「FFmpeg 理论上支持的」。**
**所以官方完整版、系统包管理器版、自己编的版本,三个数可以完全不同。**
**这也解释了 1.1.2 那个现象:同一段命令,在别人机器上能跑,在你这里报找不到格式。**
**不是命令错了,是你这份构建里没有那个组件。**
**③ 查一个具体格式在不在,别靠翻表**
想确认 命令 看什么
---------------------------------------------------------------------
格式在不在 ffmpeg -formats | grep 名字 有没有那一行
能不能写 同上,看 e 标记 有没有 e
某文件是什么格式 ffprobe -show_format format_name
**第一行的 `grep` 是日常最高频的一条命令,比记格式名有用。**
**注意要 grep 小写——FFmpeg 的格式名区分大小写。**
最后两行就是 -demuxers 与 -muxers 的行数,而它们加起来比总数多出 136。
这个「多出来的部分」正是「读写都行」那一类被算了两遍,
所以三张表对不上不是数据错了,是统计口径不同。
第一行 414 和真 ffmpeg 上的数字不一定一样,这不是 bug。 沙箱里的这 414 是 PyAV 打包进来的那份 libavformat 的组件数, 换一份构建,三个数都会变——这正是本节第三段要讲的那件事。
「只能写」这一类最容易让人意外:居然有格式读不了自己写的文件。
它们多是 pipe:、fd:、md5 这类「目的地」而不是「文件格式」,
所以「读」这个概念对它本来就不成立。
30 秒实验
- 数列数:
ffmpeg -formats | wc -l,和自己那份构建的 414 对比。 - 查一个格式:
ffmpeg -formats | grep mp4,看它前面是D、E还是DE。 - 只列能写的:
ffmpeg -muxers,这个数就是-formats里带e的那些。
常见误区
- 把
-formats的行数当成「能读的格式数」。里面有一半多是只能写的,得看字母标记。 - 以为三个数加起来该等于 414。
d与e两个口径都含「读写都行」,重复计数是正常的。 - 拿网上截图里的格式数当标准。这个数完全取决于编译时带了哪些库。
自测三问(点开对答案)
1. `-formats` 里 `DE` 这个标记说明什么? —— 既能解封装也能封装,也就是这个格式既能读也能写,比如 mp4、mkv。 2. `-demuxers` 368 行、`-muxers` 182 行,为什么加起来不是 414? —— 因为「读写都行」的 136 个在两个清单里都出现了一次,两边相加就多算了一遍。 3. 为什么同样一条命令在别人机器上能跑,在我这里报找不到格式? —— 因为格式是编译进二进制的,两份构建注册的组件不同,跟命令对错无关。- ☐ (本节完,下一节 3.11.2 -muxers)