ffmpeg 转、ffplay 放、ffprobe 看,三个 exe 是同一个内核的三个外壳。 所以它们认识的格式完全一样,区别只在对外的那层。
1.2 装完了,这一节看看装到的三个程序各干什么。 1.3.2 往下走一层,看它们调的是哪些库。
一、三个外壳,一个内核
它们的分工可以一句话说完:
工具 输入 输出 压在哪些库上
ffmpeg 文件或流 文件或流 format + codec + filter ffplay 文件或流 一个窗口 上面三个再加 SDL ffprobe 文件或流 文字 主要只用 format
三个都建立在同一套 libav* 上,所以「ffprobe 认得的格式 ffmpeg 一定认得」。 反过来不成立:ffmpeg 能编码,ffprobe 根本不管编码。
这个关系决定了一件事:排障时先用 ffprobe 看清输入,再用 ffmpeg 处理。 跳过第一步直接转,参数猜错的地方就找不出来了。
二、ffmpeg -formats 的那两列
这份清单每行后面有个字母,很多人扫一眼就过,其实信息量很大:
标记 含义 能干什么
D 能解封装(Demux) 能作为输入读进来 E 能封装(Mux) 能作为输出写出去 DE 读写都行 可以做中转,转封装靠它们
所以「mp4 能不能转成 webm」这种问题,看两行的标记就知道: mp4 有 D,webm 有 E,两个都是 DE,走得通。
只有 D 的那些多半是老采集格式,只有 E 的多半是输出专用。 做转封装时两边必须都能读能写,中间那一段才成立。
三、ffplay 不只是播放器
很多人装了 ffplay 从来不用,其实它是最好用的调试工具:
用法 能看出什么
ffplay 文件 最快确认这个文件到底能不能放 ffplay -stats 文件 实时码率、帧率、音视频偏差 ffplay -vf 滤镜 文件 直接预览滤镜效果,不落盘 ffplay -af 滤镜 文件 预览音频滤镜,比如响度归一
第三行是最有价值的:写滤镜链时不用先转一个文件出来看效果,直接预览。 调一次参数只要几秒,比「转一遍再看」快一个数量级。
Windows 上的 ffplay 还带一个隐藏好处:它不依赖任何播放器框架。 系统自带的播放器打不开的怪文件,ffplay 往往能放——因为它用的是 FFmpeg 自己的解码器。
四、ffprobe 的价值是「只看不动」
它是三个里最不显眼、用得最多的一个:
问什么 参数 输出什么
有几条流 默认就够 每个流的类型与编码 每帧多大 -show_frames 逐帧的大小与类型 每个包多大 -show_packets 逐包的时间戳与大小 格式总览 -show_format 时长、码率、元数据
这四个参数基本覆盖了「这个文件是怎么回事」的所有问题。
调不动参数的时候,先 -show_packets 看一眼包的时间戳,问题常常自己就露出来了。
它还有一个别的工具做不到的事:-print_format json。
把输出变成 JSON,程序直接解析,不用去切字符串。
做自动化的时候,这一项比什么都重要。
五、动手 Demo:ffmpeg 转、ffplay 放、ffprobe 看
这一段把三个工具压的库摊开,再把 formats 清单的 D/E 分布数出来。 顺带说清楚 rtmp 为什么不在格式表里。
import av
both = inn = out = 0
for n in av.formats_available:
f = av.format.ContainerFormat(n)
if f.is_input and f.is_output:
both += 1
elif f.is_input:
inn += 1
elif f.is_output:
out += 1
print(u"只能读", inn, u"只能写", out, u"都能", both)
for n in (u"mp4", u"rtmp"):
try:
print(n, av.format.ContainerFormat(n).long_name)
except Exception as e:
print(n, u"不在格式表里")
实跑输出:
--------------------------------------------------------------------
三个工具——ffmpeg 转、ffplay 放、ffprobe 看
--------------------------------------------------------------------
**① 三个 exe,分工是三句话**
工具 干什么 压在哪些库上
------------------------------------------------------------------
ffmpeg 转码、转封装、加滤镜 format + codec + filter
ffplay 播出来,带窗口与波形 上面三个再加 SDL
ffprobe 只看不转,把信息打出来 只需要 format
**三个工具是同一份库的三个外壳,所以它们认识的格式完全一样。**
**ffprobe 能读出来的东西,ffmpeg 一定也能读;区别只在 ffmpeg 顺手把它转了。**
**② ffmpeg -formats 那两列 D 和 E,在这儿能数出来**
能力 格式数 对应标记 是什么
----------------------------------------------------------------------
只能解封装 232 d 能读不能写,多是老采集格式
只能封装 46 e 能写不能读,多是输出专用
读写都行 136 de mp4、flv、ts 这类主力
合计 414 — 就是 ffmpeg -formats 的行数
**能读的 368 个、能写的 182 个——读的比写的多一倍。**
**做转封装时「从什么转到什么」,可行性就在这两列里:**
**两边都得能读能写,中间才走得通。**
**③ 顺手把一个常踩的坑说清:rtmp 不在这张表里**
名字 在格式表里吗 它其实是什么
------------------------------------------------------
mp4 在 封装格式,管文件怎么排
flv 在 封装格式,管文件怎么排
mpegts 在 封装格式,管文件怎么排
rtmp 不在 传输协议,管流怎么送
**格式管「码流怎么摆进文件」,协议管「字节怎么走上网络」,是两层东西。**
**所以查不到 rtmp 不代表不能用——它是被登记在协议表里的。**
**上一门课栽过的那个坑就是这个:库能编出 flv 封装,但没编进 rtmp 协议,**
**open 照样返回成功,一个字节都不发。**
第一张表把三个工具的分工和它们依赖的库对应起来。 ffprobe 只用 format 层,所以它最轻、也最快。
第二张表是 D/E 标记的量化:能读的 368 个,能写的 182 个。 读的比写的多一倍——所以「什么都能打开,但不是什么都能存」。
第三张表点出一个常踩的坑:rtmp 不在格式表里。 格式管「码流怎么摆进文件」,协议管「字节怎么走上网络」,是两层东西。
上一门课栽过的坑就是这个:库能编出 flv 封装,但没编进 rtmp 协议。 open 照样返回成功,一个字节都不发——「能打开」不等于「能工作」。
30 秒实验
- 数标记:
ffmpeg -formats | grep "^ DE"数出读写都行的格式。这个数是你能做转封装的格式对数。 - 先看再转:拿一个不认识的文件,先
ffprobe 文件看有几条流、什么编码,再决定用什么参数转。这个顺序能省掉一半的试错。 - 预览滤镜:
ffplay -vf scale=320:-1 文件,把 320 换成别的数值,直接看效果,不产生任何临时文件。
常见误区
- 以为装了 ffmpeg 就有 ffplay。三个 exe 是一起发的,但有些精简包会删掉 ffplay 省体积。
where ffplay查一下就知道。 - 以为 ffprobe 只能看信息所以没用。它是唯一能给出「逐帧逐包」细节的工具,调参数时离不开它。
- 把「能打开」当成「能工作」。协议缺失时 open 可能成功但一个字节都不发。判断标准是真跑一次,看输出有没有增长。
自测三问(点开对答案)
1. ffprobe 能不能把一个 mp4 转成 flv? —— 不能。它只解封装、不解码也不编码,更不封装输出。转封装要用 ffmpeg,加上 `-c copy`。 2. `ffmpeg -formats` 里某一行标着 `D`,说明什么? —— 这个格式可以作为输入读进来。没有 E 就不能作为输出写出去,所以它做不了目标格式。 3. 为什么 rtmp 不在格式表里,却能用 `-f flv rtmp://...`? —— rtmp 是传输协议不是封装格式。`-f flv` 指定的是封装,rtmp:// 那部分交给协议层处理。两层各管各的。- ☐ (本节完,下一节 1.3.2 SDK)