🎬 第三章 FFmpeg三大常用工具及应用选项详解
📄 一句话概括

muxer 就是「封装器」,决定输出文件长什么样。 -muxers 这 182 个里,一半是存文件,一半是「送到某个地方」。

📝 本节和前面几节的关系

3.11.1 讲了全集,这一节只看能写的那一半。 因为「输出成功但打不开」这类问题,几乎都跟封装器选错有关。

一、182 个能写的,用途分三类

先看清这 182 是怎么凑出来的:

项 值 说明


-muxers 行数 182 只能写 46 + 读写都行 136 含容器格式 136 mp4/mkv/flv/ts 这类 含输出专用 46 设备、管道、网络协议封装

第二行和第三行的区别值得说清:一个「存成文件」,一个「送到某个地方」。 -f flv 可能是写文件,也可能是推流——取决于后面跟的是路径还是 URL。

所以「输出成不成功」这句话要拆开看: 写文件成功只看磁盘,推流成功要看对端收到没有。

二、六个常见 muxer 与它的脾气

日常用得最多的就这么几个,各有各的限制:

muxer 名 扩展名 特点


mp4 .mp4 .m4v 兼容最好,索引在文件尾 matroska .mkv 什么都能装,索引边写边记 flv .flv 直播标配,延迟低 mpegts .ts 广播与 HLS 的底层 webm .webm 网页用,只吃 vp8/vp9/opus image2 .png .jpg 序列帧,一帧一个文件

第五行是个硬限制:webm 只接受特定几个编码,塞 h264 进去会直接报错。 这不是 ffmpeg 的问题,是 webm 这个规范本身就这么定的。

第一行那个「索引在文件尾」有实际后果:录制中断的 mp4 常常打不开。 因为索引还没写上去。要边录边能播,得选 mkv 或 ts 这类索引边写边记的。

三、什么时候必须写 -f

不写 -f 时 ffmpeg 靠扩展名猜封装器,猜不到就报错。三种情况必须显式写:

场合 为什么要写 -f 例子


输出到管道 没有扩展名可猜 -f mpegts pipe:1 扩展名有歧义 多个 muxer 抢同一个后缀 -f mp4 out.tmp 推到网络 靠 -f 定封装协议 -f flv rtmp://…

报错信息几乎总是「Unable to find a suitable output format」。 这句的意思基本就是「加个 -f 告诉我」,不是文件坏了、也不是权限问题。

第二行是最容易被忽略的:.tmp、.dat 这类后缀没有对应 muxer, 不写 -f mp4 就一定会报错,而很多人会以为是「临时文件不能写」。

四、动手 Demo:能写的 182 个,按用途分三类

接着上一段的数据,只看「能写」的那一侧。 重点是把「存文件」和「送出去」这两类分开,因为它们成功的标准完全不一样。

import av

files, sinks = [], []
both = out = 0
for n in sorted(av.formats_available):
    try:
        f = av.format.ContainerFormat(n)
    except Exception:
        continue
    if not f.is_output:
        continue
    if f.is_input:
        both += 1
    else:
        out += 1
    if f.extensions:
        files.append(n)
    else:
        sinks.append(n)

print(u"-muxers 行数  %d" % (both + out))
print(u"读写都行      %d" % both)
print(u"只能写        %d" % out)
print(u"有扩展名的    %d" % len(files))
print(u"没有扩展名的  %d" % len(sinks))

实跑输出:

--------------------------------------------------------------------
3.11.2 -muxers——能写的 182 个,按用途分三类
--------------------------------------------------------------------

**① muxer 就是「封装器」,决定输出文件长什么样**

  项               值      说明
  ------------------------------------------------------
  -muxers 行数     182     只能写 46 + 读写都行 136
  含容器格式       136     mp4/mkv/flv/ts 这类
  含输出专用       46      设备、管道、网络协议封装

**第二行和第三行的区别值得说清:一个是「存成文件」,一个是「送到某个地方」。**
**`-f flv` 可能是写文件,也可能是推流——取决于后面的地址是路径还是 URL。**

**② 常见 muxer 与它的扩展名**

  muxer 名     扩展名        特点
  ----------------------------------------------------------
  mp4          .mp4 .m4v     兼容最好,索引在文件尾
  matroska     .mkv          什么都能装,索引边写边记
  flv          .flv          直播标配,延迟低
  mpegts       .ts           广播与 HLS 的底层
  webm         .webm         网页用,只吃 vp8/vp9/opus
  image2       .png .jpg     序列帧,一帧一个文件

**第五行是个硬限制:webm 只接受特定几个编码,塞 h264 进去会报错。**
**这不是 ffmpeg 的问题,是 webm 这个规范本身就这么定的。**

**③ 用 -f 强制指定,什么时候需要**

  场合             为什么要写 -f               例子
  -----------------------------------------------------------------
  输出到管道       没有扩展名可猜              -f mpegts pipe:1
  扩展名有歧义     多个 muxer 抢同一个后缀     -f mp4 out.tmp
  推到网络         靠 -f 定封装协议            -f flv rtmp://…

**不写 `-f` 时 ffmpeg 靠扩展名猜,猜不到就报「Unable to find a suitable output format」。**
**这句报错的意思几乎总是「加个 -f 告诉我」,不是文件坏了。**

第三行「没有扩展名」的那一批,就是「送到某个地方」的输出专用格式。 它们本来就不该有扩展名——你没法给一个管道或者一个 md5 摘要起后缀名。

所以 -muxers 那张表不是「文件格式清单」,是「输出目的地清单」。 这个认识一改,很多疑问就消了:为什么 md5 也在里面、为什么 pipe 也在里面。

最后两行是「有扩展名」与「没有扩展名」的个数对比,两者相加就是那 182。 而「有扩展名」的那一批正是能靠后缀反查的那批—— 一个 muxer 声明多个后缀,这些后缀下的文件就都由它负责输出。

30 秒实验

  1. 数能写的:ffmpeg -muxers | wc -l,与 -formats 里带 e 的行数对比。
  2. 查 mp4 的后缀:ffmpeg -muxers | grep mp4,看它声明了哪些扩展名。
  3. 故意不写 -f:ffmpeg -i 片子.mp4 out.tmp,看那句 Unable to find 报错。

常见误区

  1. 以为 -muxers 里全是「文件格式」。里面还有管道、网络封装、摘要这类目的地。
  2. 输出到 .tmp 时不写 -f。后缀没有对应 muxer,必然报找不到输出格式。
  3. 以为 mp4 是最保险的输出。中断录制时它常常打不开,因为索引还没写到文件尾。
自测三问(点开对答案) 1. 为什么 `-muxers` 里会出现 md5、pipe 这种不像文件格式的条目? —— 因为 muxer 管的是「输出目的地」而非「文件格式」,管道和摘要也是输出目的地。 2. 报 `Unable to find a suitable output format` 通常怎么解决? —— 显式加 `-f 封装器名` 告诉 ffmpeg 用哪个 muxer,通常不是文件或权限的问题。 3. 要边录边能播,为什么优先选 mkv 而不是 mp4? —— mp4 的索引写在文件尾,中断就没索引;mkv 边写边记索引,中断也能播。

相关笔记