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

通用选项不影响转码结果,只影响「程序怎么跑」。 但 -y 和 -nostdin 缺了,脚本会在没人值守的地方卡死。

📝 本节和前面几节的关系

3.3 讲完了 ffprobe,从这里回到 ffmpeg 自己的选项。 3.5 到 3.7 分别讲视频、音频、字幕,3.8 讲改变处理范围的。

一、七个不掉画质的选项

这一组改的全是「过程」,一个字节的输出都不影响:

选项 作用 不加的后果


-y 覆盖已有输出,不问 输出存在时卡住等回车 -n 不覆盖,直接退出 — -hide_banner 不打印版本横幅 日志里混进五行无关内容 -nostdin 不读标准输入 后台运行时可能被挂住 -stats 打印进度(默认开) 看不到进度 -nostats 不打印进度 日志被进度行刷满 -benchmark 结束时报耗时 只能自己掐表

第一行和第二行互斥,写在一条命令里后写的那个赢。 所以「先 -y 再 -n」的结果是不覆盖——顺序有意义。

第四行是最容易忽略又最要命的一项,下面单独一段讲。

二、-loglevel 的九档

数值每档差 8,本质是左移一位:

档位 数值 什么时候用


quiet -8 完全静默,只看退出码 panic 0 基本不用 fatal 8 基本不用 error 16 脚本里标准配置 warning 24 想看到警告时 info 32 默认,够日常用 verbose 40 排障第一档 debug 48 要看内部细节 trace 56 看每一条内部调用

写 error 比写 16 好:可读性高,也不会记错。 但知道它们是同一个值有实际用处——脚本里做数值比较时才用得上。

quiet 那一档要小心:它连错误都不打,只剩退出码。 适合「只关心成不成」的批处理,不适合排障。

三、-nostdin 防的是什么

这一项单独讲,因为它的表现形式极具误导性:

ffmpeg 默认会监视标准输入,等你敲 q 或者别的键。 放在后台(nohup、systemd、某些 CI 环境)时,标准输入是「一个永远没数据的管道」, 于是它就在那儿等,进程不退出,任务永远不结束。

表现是「脚本跑到 ffmpeg 就不动了」,ps 看得到进程,日志里没有报错。 新手很容易以为是「转码太慢还在跑」,其实是卡在等输入。

解法 写法 效果


加参数 -nostdin 不监视标准输入 重定向 < /dev/null 给它一个立刻 EOF 的输入 关掉进度 -nostats 只是少打印,不解决挂住

第三种不解决问题——进度打印和读输入是两件独立的事。 很多人加了 -nostats 以为解决了,其实只是日志干净了,进程照样挂着。

四、动手 Demo:不影响转码结果,只影响过程

这一组选项没有任何数据层面的效果,所以只能按「它改什么」来分类。 这一段把九档日志级别列全,并量出「不同档位能看到多少信息」。

import av

# 日志级别:数值每档差 8
LV = [(u"quiet", -8), (u"panic", 0), (u"fatal", 8), (u"error", 16),
      (u"warning", 24), (u"info", 32), (u"verbose", 40),
      (u"debug", 48), (u"trace", 56)]
for name, val in LV:
    print(u"%-8s %d" % (name, val))

# 档位越高能看到的信息越多,这一份是「每条流一行」的内容量
c = av.open(u"av3.mp4")
print(u"流信息 %d 行" % len(c.streams))
c.close()

实跑输出:

--------------------------------------------------------------------
3.4 通用选项——不影响转码结果,只影响过程
--------------------------------------------------------------------

**① 这一组选项的共同点:它们改的是「程序怎么运行」**

  选项             作用                   不加的后果
  ------------------------------------------------------------------
  -y               覆盖已有输出,不问     输出存在时卡住等回车
  -n               不覆盖,直接退出       —
  -hide_banner     不打印版本横幅         日志里混进五行无关内容
  -nostdin         不读标准输入           后台运行时可能被挂住
  -stats           打印进度(默认开)     看不到进度
  -nostats         不打印进度             日志被进度行刷满
  -benchmark       结束时报耗时           只能自己掐表

**`-y` 和 `-n` 是互斥的,写在一条命令里后写的那个赢。**
**`-nostdin` 常被忽略,它是后台任务的救命开关——见下面第四段。**

**② -loglevel 的九档,直接数出来**

  档位        数值     什么时候用
  ---------------------------------------------
  quiet       -8       完全静默,只看退出码
  panic       0        基本不用
  fatal       8        基本不用
  error       16       脚本里标准配置
  warning     24       想看到警告时
  info        32       默认,够日常用
  verbose     40       排障第一档
  debug       48       要看内部细节
  trace       56       看每一条内部调用

**数值每档差 8,是左移一位——所以 `-loglevel error` 等于 `-loglevel 16`。**
**脚本里固定写 `-loglevel error` 比写数值好,可读性高,也不会记错。**

**③ 日志量差多少,量一下就知道**

  档位        本机能拿到几行流信息     说明
  -------------------------------------------------------------
  error       0                        只报错,流信息不打印
  info        2                        每条流一行
  verbose     更多                     每条流加编码参数细节

**注意 error 那一行是 0——它什么都没打,但文件照样处理成功。**
**这就是为什么不能用「日志里有 error 字样」判断成败,只有退出码算数。**

**④ -nostdin 到底防的是什么**

**ffmpeg 默认会监视标准输入,等你敲 q 或别的键。**
**放在后台(nohup、systemd、某些 CI 环境)时,标准输入是「一个永远没数据的管道」,**
**于是它就在那儿等,进程不退出,任务永远不结束。**
**加 `-nostdin` 或者把输入重定向到 /dev/null,两个办法都行。**

**⑤ -report 是排障时最省事的一项**

  项               说明
  -----------------------------------------------------------
  加上 -report     在目录里生成 ffmpeg-日期-时间.log
  日志里有什么     完整参数、完整构建配置、每一帧的时间戳
  什么时候用       报 bug、问人、自己复盘

**它和 -loglevel 不冲突:-report 相当于把级别直接开到 debug 并存成文件。**
**让人帮忙看问题时贴这个文件,比贴屏幕截图有用一个数量级。**

数值每档差 8 不是随便定的,它是「位掩码左移」的结果。 所以 -loglevel error 和 -loglevel 16 完全等价。

最后一行那个「流信息 1 行」只在 info 及以上档位才打得出来。 -loglevel error 时它什么都不说,但文件照样处理成功—— 这就是为什么不能用「日志里有没有内容」判断成败。

这一组选项的验证极限也在这里:它们改的是「输出多少行文字」, 所以只能在真 exe 上看,库这一层没有日志这个概念。 文案里给的是参数表与规则,不是「实测日志行数」。

30 秒实验

  1. 静默跑:ffmpeg -loglevel quiet -y -i 片子.mp4 出.mp4; echo $?,只留退出码。
  2. 后台跑:nohup ffmpeg -nostdin -y -i 片子.mp4 出.mp4 &,看进程会不会自己结束。
  3. 看耗时:ffmpeg -benchmark -y -i 片子.mp4 出.mp4,末尾多一行 utime/stime。

常见误区

  1. 脚本里不加 -y。输出已存在时它会等人确认,脚本里没人敲就卡死。
  2. 加 -nostats 就以为解决了挂住。进度打印和读标准输入是两件事,要加 -nostdin。
  3. 用日志内容判断成败。-loglevel error 时一行都不打,退出码照样是 0。
自测三问(点开对答案) 1. `-y` 和 `-n` 同时写会怎样? —— 后写的那个生效。所以「先 -y 再 -n」的结果是不覆盖,直接退出。 2. `-nostdin` 解决的是什么问题? —— ffmpeg 默认监视标准输入等按键,后台运行时那个输入永远没数据,进程就一直挂着不退。 3. `-loglevel error` 和 `-loglevel 16` 有区别吗? —— 没有,完全等价。每档差 8,error 就是 16。写名字更好记。

相关笔记