通用选项不影响转码结果,只影响「程序怎么跑」。 但 -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 秒实验
- 静默跑:
ffmpeg -loglevel quiet -y -i 片子.mp4 出.mp4; echo $?,只留退出码。 - 后台跑:
nohup ffmpeg -nostdin -y -i 片子.mp4 出.mp4 &,看进程会不会自己结束。 - 看耗时:
ffmpeg -benchmark -y -i 片子.mp4 出.mp4,末尾多一行 utime/stime。
常见误区
- 脚本里不加
-y。输出已存在时它会等人确认,脚本里没人敲就卡死。 - 加
-nostats就以为解决了挂住。进度打印和读标准输入是两件事,要加-nostdin。 - 用日志内容判断成败。
-loglevel error时一行都不打,退出码照样是 0。
自测三问(点开对答案)
1. `-y` 和 `-n` 同时写会怎样? —— 后写的那个生效。所以「先 -y 再 -n」的结果是不覆盖,直接退出。 2. `-nostdin` 解决的是什么问题? —— ffmpeg 默认监视标准输入等按键,后台运行时那个输入永远没数据,进程就一直挂着不退。 3. `-loglevel error` 和 `-loglevel 16` 有区别吗? —— 没有,完全等价。每档差 8,error 就是 16。写名字更好记。- ☐ (本节完,下一节 3.5 视频选项)