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

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 秒实验

  1. 数能编的:ffmpeg -encoders | wc -l,与 -codecs 的行数对比。
  2. 真编一帧:ffmpeg -f lavfi -i testsrc -frames:v 1 -c:v libx264 out.mp4,比看清单可靠。
  3. 查它的参数:ffmpeg -h encoder=libx264,看 -preset 与 -crf 的范围。

常见误区

  1. 以为 -encoders 里有就能用。动态库缺失时列表里有、一编就报错,要真编一帧验证。
  2. 把 lossless=True 当成「libx264 无损」。它只是「支持无损模式」,默认路径是有损的。
  3. 以为「能编」的门槛和「能解」一样。编出来的码流要合规,比读懂别人难得多。
自测三问(点开对答案) 1. 为什么能编的编码器只有能解的三分之一左右? —— 因为解码只需读懂别人的码流,而编码要产出符合规范的码流,合规门槛高得多。 2. `libx264` 的 `lossless` 与 `lossy` 同时为 True,怎么理解? —— 它两种模式都支持:默认走有损,要无损得显式指定 `-qp 0`,两者并不矛盾。 3. 列表里有 libx264,一编就报错,最可能是什么原因? —— 运行时找不到对应的动态库(Windows 上缺 dll),报错里通常会直接写出缺哪个文件。

相关笔记