读书笔记 · 约 19,060 字 · 预计推送 2 部分

FFmpeg 命令工程配方手册:转码、压缩、字幕、批处理(主题精读) 未开始

目录

题记与说明

- 日期:2026-10-31(夜航精读任务 knowledge-p5j2vm4l-2)
- 形式:主题研究(topic research)——先检索精读 7 个来源,再整合为可复用的个人配方手册,关键配方在本机逐条实测验证
- 本机验证环境:ffmpeg version 9.0.2-full_build-www.gyan.dev(gcc 16.2.0 / MSYS2,--enable-libx264 --enable-libx265 --enable-libsvtav1 --enable-libass --enable-fontconfig),Windows 11 x64,nproc=24 逻辑核
- 实测素材:testsrc2 合成彩条 1280×720@30fps ×10 s + 440 Hz 正弦音 AAC 128k(生成命令见附录 A),6,171,001 字节,总码率 4,936,800 bit/s
- 标注约定:每条配方末尾的「✅ 本机实测」表示我在本会话用本机 ffmpeg 9.0.2 实际运行并记录了输出;「📖 来源」为文献依据,引述保持英文原文

一、来源清单与阅读方式

#来源性质读取方式
1FFmpeg 官方 Wiki《H.264 Video Encoding Guide》官方编码指南(CRF/preset/tune/两遍/无损/FAQ)trac.ffmpeg.org 有 Anubis 反爬(PoW 验证,工具直接访问返回 "Making sure you're not a bot!"),改经 Wayback Machine 2024 存档 全文读取
2FFmpeg 官方 Wiki《HowToBurnSubtitlesIntoVideo》官方字幕烧录指南同上,经 Wayback 存档 全文读取
3Werner Robitza(slhck)《CRF Guide (Constant Rate Factor in x264, x265 and libvpx)》(2017-02-24)FFmpeg wiki 主要维护者之一对 CRF 原理的专文webReader 全文读取
4Werner Robitza(slhck)《Understanding Rate Control Modes (x264, x265, vpx)》(2017-03-01,含 2019-2020 更新)码率控制模式(CQP/ABR/CBR/两遍/CRF/VBV)决策专文,含 Big Buck Bunny / Tears of Steel 对比实验webReader 全文读取
5Bannerbear《How to Add Subtitles to a Video File Using FFmpeg》(Josephine Loo,2022-07,2024-01 更新)硬/软字幕实操教程(mov_text 多轨、force_style)WebFetch 提取(命令为原文精确提取,散文部分为提取器转述,文中已标注)
6Mux《How to compress video files while maintaining quality with FFmpeg》视频平台方的压缩实操文(目标体积公式、preset 取舍数字)WebFetch 提取(三条关键主张为页面原句摘取)
7Brainiarc7《ffmpeg-multi-instances-xargs》(GitHub Gist)FFmpeg wiki 资深贡献者的多实例并行批处理配方(NVENC 场景)webReader 全文读取

辅助检索(结论只作旁证,未逐字精读):Video SE:veryfast preset 反而更小的已知现象、Super User / ahosting 关于并行 ffmpeg 的 CPU 超订与磁盘 I/O 讨论、Discord 压缩脚本的 0.97 安全系数写法。


二、七维提取

1. 核心问题

FFmpeg 是"天书式"工具:选项上千、参数顺序敏感、网络教程互相矛盾(尤其码率控制),普通使用者每次都要现搜现拼。这份精读要解决的是:如何把高频的转码、压缩、字幕、批处理需求,沉淀为一套参数有依据、行为经实测、拿来即用的个人配方库,并弄清每个配方背后的选择逻辑(什么时候用 CRF、什么时候两遍、硬字幕还是软字幕、批处理怎么不翻车)。

2. 主要主张

  1. 码率控制只有两件事值得记:官方 wiki 开宗明义——"There are two rate control modes that are usually suggested for general use: Constant Rate Factor (CRF) or Two-Pass ABR."。存档求质量用 CRF(单遍、恒定质量、体积不可预知);体积必须命中用两遍 ABR。裸 ABR(只给 -b:v)是被 x264 核心开发者点名"永远不要用"的模式。
  2. CRF 的算术很简单:x264 合理区间 17–28(默认 23),x265 默认 28;±6 ≈ 体积减半/翻倍。"visually lossless" 用 17–18。
  3. preset 是"速度换压缩率"的旋钮:"Use the slowest preset that you have patience for.";同一 CRF 下越慢体积越小,placebo 只比 veryslow 好 ~1% 却慢得多,官方直接叫别用。
  4. 字幕的决策只有一条分界线:要可开关/可移除/不重编码 → 软字幕(MP4 用 -c:s mov_text,MKV 直接 -c:s copy);要所有播放器必显 → 硬字幕(subtitles/ass 滤镜烧录,必须重编码,依赖 libass)。中文场景的关键坑是字体(fontconfig)与 SRT 的 UTF-8 编码。
  5. 批处理的安全要点不是转码参数而是工程细节:文件名引号、-y/-n 覆盖语义、退出码不可全信(本机 9.0.2 实测"拒绝覆盖"竟返回 0)、并行度要远小于核数(ffmpeg 单进程已多线程,-P 2 这类保守并行才是 gist 推荐)。

3. 方法

4. 数据与证据

文献证据:见 §五逐条引述(含官方 wiki 的 preset 编码时间曲线数据、slhck 的 BBB/ToS 码率曲线实验、Mux 的经验数字)。
本机实测证据(ffmpeg 9.0.2,合成素材 720p/10s,详见 §六):

5. 结论

11 条配方可覆盖日常 90%+ 的 ffmpeg 需求;"CRF 存档、两遍给体积、copy 优先、字幕先问软硬、批处理管好文件名/覆盖/并行" 五句话是整本手册的压缩表示。所有配方的参数选择都有官方 wiki 或 wiki 维护者背书,行为差异(退出码、AV1 表现)以本机实测为准。

6. 局限

  1. trac.ffmpeg.org 只能读 Wayback 2024 存档,wiki 可能已有更新(文中标注存档日期)。
  2. 实测素材是合成的 testsrc2 彩条(高频细节+运动),压缩率与真实拍摄素材不可直接换算;CRF/preset 的相对趋势可信,绝对数值只对本类素材有效。
  3. 实测仅一台 Windows 机器(24 逻辑核、gyan full build);退出码行为在别的版本/平台可能不同(例如官方文档语义上失败应非零)。
  4. Bannerbear/Mux 两篇经 WebFetch 模型提取,散文部分是转述而非逐字原文(已标注;命令部分为精确提取)。
  5. 未覆盖直播推流、硬件编码器调优(NVENC/QSV/AMF 仅收录官方示例未实测)、字幕样式深入定制(ASS 全语法)。

7. 对我的启发

  1. 配方库思维:高频 CLI 工具值得沉淀成"带默认值的函数"而不是每次重搜——下一步可把 R1/R4/R6/R7/R8 写成本地 shell 函数或 PowerShell 脚本,参数只暴露 CRF/目标体积/字幕路径三个口。
  2. 决策树先于参数:每个 ffmpeg 问题先问"场景四选一(存档/点播/直播/设备)"再选码率控制,能避免网络教程最常见错误(裸 -b:v)。
  3. 信任但验证:教程(包括官方 wiki 的 Windows 提示)在本机一律先小段试编(-ss+-t 预检配方 R10);退出码这类"看似理所当然"的工程假设必须实测——本次就抓到一个 exit=0 陷阱。
  4. 字节级验证法可复用:faststart 是否生效、字幕是否真的烧进去(抽帧目检)、软字幕是否无损(往返提取 diff)——都可用"最小可观测证据"验证,不必依赖播放器肉眼。

三、心智模型:一条 ffmpeg 命令的解剖

ffmpeg [全局选项] -i 输入 [输入选项] -vf/-filter_complex [滤镜] [输出选项] 输出
  ffprobe -v error -show_entries format=duration,size,bit_rate -show_entries stream=codec_name,width,height,pix_fmt -of default=noprint_wrappers=1 输入.mp4
  ffprobe -v error -print_format json -show_format -show_streams 输入.mp4   # 给脚本用

四、配方手册正文(R0–R10)

R0 · 探查配方:先看清楚再动手

ffprobe -v error -print_format json -show_format -show_streams input.mp4

✅ 本机实测:正确输出 h264/High/1280×720 等字段。脚本里用 -of json 或 -show_entries 精确取字段。

R1 · 标准转码(H.264,恒定质量,默认首选)

ffmpeg -i input -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv      # 官方 wiki 示例
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mp4      # Mux 示例

📖 来源 1(原文):"The range of the CRF scale is 0–51, where 0 is lossless (for 8 bit only, for 10 bit use -qp 0), 23 is the default, and 51 is worst quality possible. A lower value generally leads to higher quality, and a subjectively sane range is 17–28."
📖 来源 1(原文):"The range is exponential, so increasing the CRF value +6 results in roughly half the bitrate / file size, while -6 leads to roughly twice the bitrate."
📖 来源 3(原文):"For x264, sane values are between 18 and 28. The default is 23, so you can use this as a starting point.";x265 默认 28:"ffmpeg -i input.mp4 -c:v libx265 -crf 28 output.mp4"
✅ 本机实测 CRF 阶梯(preset medium,-c:a copy):

CRF耗时体积相对上一档
180.881 s5.82 MiB—
230.847 s3.78 MiB×0.650
280.834 s1.94 MiB×0.513(≈官方"±6 减半")
330.838 s1.14 MiB×0.585

何时用:归档、网盘、自己收藏——一切"体积不设上限、质量要尽量好"的场景(来源 4 的场景 1 Archival)。

R2 · 高压缩转码(H.265 / AV1)

ffmpeg -i input.mp4 -c:v libx265 -tag:v hvc1 -preset medium -crf 28 -c:a copy out.mp4
ffmpeg -i input.mp4 -c:v libsvtav1 -crf 30 -c:a copy out.mkv

📖 来源 6(页面原句):"H.265 (HEVC) achieves approximately 50% better compression than H.264 at equivalent quality"(同质量体积约减半;编码时间 2–3×)。
📖 来源 3:VP9 恒定质量写法 -c:v libvpx-vp9 -crf 31 -b:v 0(-b:v 0 必须加,VP9 的 CRF 需要关掉默认 ABR)。
✅ 本机实测(合成素材):libx265 crf28/medium = 2.60 MiB / 2.346 s(对比 x264 crf23 的 3.78 MiB / 0.885 s:小 31%,慢 2.6×,方向与文献一致);libsvtav1 crf30 = 5.41 MiB / 1.274 s——在合成彩条上反而大于 x264 crf23。教训:CRF 数值跨编码器不可比(来源 3 原文本就说明 CRF 结果取决于源复杂度),AV1 要发挥优势需按素材重调 crf/preset。
⚠️ -tag:v hvc1 让 QuickTime/苹果系能识别 HEVC 轨。

R3 · preset 旋钮:用时间换体积

📖 来源 1(原文):"A preset is a collection of options that will provide a certain encoding speed to compression ratio. A slower preset will provide better compression (compression is quality per filesize)." 及 "Use the slowest preset that you have patience for."(速度序:ultrafast→superfast→veryfast→faster→fast→medium(默认)→slow→slower→veryslow→placebo)
📖 来源 1 FAQ 数据:medium→slow 编码时间 +40%,→slower 翻倍,→veryslow 需 280% 时间;placebo 仅比 veryslow 好 ~1%,"ignore this as it is not useful"。
✅ 本机实测(crf23):

preset耗时体积
ultrafast0.415 s8.93 MiB(比源文件 crf18 还大!)
veryfast0.542 s3.37 MiB
medium0.885 s3.78 MiB
slow1.448 s3.69 MiB
veryslow3.256 s3.28 MiB

R4 · 目标体积压缩:两遍 ABR(体积必须命中时)

公式(官方 wiki 版,MiB→kbit/s 用 8388.608):
📖 来源 1 原文:(200 MiB * 8388.608 [converts MiB to kBit; note: not 8192 as 1 kBit is always 1000 bit]) / 600 seconds = ~2796 kBit/s total bitrate,再减去音频码率。

# 目标 1 MiB、时长 10 s:(1*8388.608)/10 - 128 ≈ 710k 视频码率
ffmpeg -y -i input -c:v libx264 -b:v 710k -pass 1 -passlogfile /tmp/pl -an -f null /dev/null
ffmpeg -i input -c:v libx264 -b:v 710k -pass 2 -passlogfile /tmp/pl -c:a aac -b:a 128k output.mp4

📖 来源 1(原文):"In pass 1, output to a null file descriptor, not an actual file. (This will generate a logfile that ffmpeg needs for the second pass.)" Windows 提示:NUL 替代 /dev/null、^ 替代续行 \。
📖 来源 6 用简化系数 8192:(target_size_MB × 8192) / duration − 音频码率——8192 比 8388.608 少算 ~2.4%,天然留了不超标的余量,两种写法都在流传,属"精确公式 vs 保守估算"之别。
✅ 本机实测:两遍跑完得 1,025,245 字节 = 0.978 MiB(目标 1.000 MiB,偏差 −2.2%,偏小是因为 AAC 对正弦音用不满 128k 且 x264 不做填位——来源 4 原文早有言:"if you have a scene that is very easy to encode, your bitrate may always end up lower than the one you specified. Don't worry about this")。
📖 来源 1 FAQ(原文):"Will two-pass provide a better quality than CRF? No, though it does allow you to target a file size more accurately." ——两遍的意义是命中体积,不是提升质量。
补充配方(capped CRF / VBV)——既要质量导向又怕码率尖峰:

ffmpeg -i input -c:v libx264 -crf 23 -maxrate 1M -bufsize 2M output.mp4          # x264
ffmpeg -i input -c:v libx265 -crf 28 -x265-params vbv-maxrate=1000:vbv-bufsize=2000 output.mp4

📖 来源 4(原文):"A good default is to have the buffer size be twice as large as the maximum rate";并给出调 CRF 的换算法:"you encode at CRF 18 without VBV. Your clip ends up with an average bitrate of 3.0 Mbit/s. But your want your VBV setting to cap the clip at 1.5 Mbit/s, so you need to increase your CRF to about 24 to only get half the bitrate."

R5 · 兼容性配方:让文件"在哪都能放"

ffmpeg -i input -c:v libx264 -crf 23 -pix_fmt yuv420p -movflags +faststart output.mp4

📖 来源 1(原文):像素格式——"You may need to use -vf format=yuv420p (or the alias -pix_fmt yuv420p) for your output to work in QuickTime and most other players."
📖 来源 1(原文):网络播放——"You can add -movflags +faststart as an output option if your videos are going to be viewed in a browser. This will move some information to the beginning of your file and allow the video to begin playing before it is completely downloaded."
✅ 本机实测(字节级):无 faststart 时 mdat 在偏移 ~40、moov 在文件尾 6,159,200;加 -movflags +faststart -c copy 后 moov 移到偏移 ~36、mdat 在 11,936——原子序验证通过。
色调映射/高源:HDR→SDR 需另加 zscale/tonemap 滤镜链(本次未实测,未收录为配方)。

R6 · 硬字幕(烧录,不可移除,全播放器必显)

# 基本式(官方 wiki)
ffmpeg -i video.avi -vf subtitles=subtitle.srt out.avi
# 字幕已内嵌在 mkv 里
ffmpeg -i video.mkv -vf subtitles=video.mkv out.mkv
# 中文字体+字号(本机 Windows 验证过的写法)
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='FontName=Microsoft YaHei,FontSize=20'" output.mp4
# ASS 样式全控:先转 ASS 再用 ass 滤镜
ffmpeg -i subtitle.srt subtitle.ass
ffmpeg -i input.mp4 -vf "ass=subtitle.ass" output.mp4

📖 来源 2(原文):"Draw subtitles on top of input video using the libass library. This filter requires ffmpeg to be compiled with --enable-libass."(本机构建已启用,ffmpeg -filters | grep subtitles 可查)
📖 来源 2(原文,剪辑陷阱):subtitles 滤镜是独立打开字幕文件的——"if you are also Seeking in the same step, then the subtitles will start at the beginning of the subtitle file";解决法是加 -copyts 并在输出端再 -ss 同值:

ffmpeg -ss 5:00.00 -copyts -i video.avi -ss 5:00.00 -vf subtitles=subtitles.srt out.avi

📖 来源 2(原文):"Windows users will have to setup font paths to get libass to work"——Windows 的 fontconfig 需要特别设置,中文场景最稳的是 force_style 显式指字体名。
📖 来源 5(Bear Tip,提取转述):ASS 颜色是 BGR 序且以 &H 开头,与 HTML 的 RGB 相反,例如 PrimaryColour=&H0000FF 是红色。
✅ 本机实测:中文 UTF-8 SRT(od -c 验证字节为 UTF-8)+ force_style='FontName=Microsoft YaHei,FontSize=20' 烧录成功(0.886 s,含重编码);抽取 2 s 处一帧 PNG 目检,字幕"这是硬字幕测试:配方手册第一行"以微软雅黑白字黑边正确渲染、底部居中。若不指定中文字体,fontconfig 默认字体缺 CJK 字形时会渲染成方框(tofu)——这是中文硬字幕第一大坑。

R7 · 软字幕(可开关,不重编码,秒级完成)

# MP4:srt → mov_text,视频音频全 copy
ffmpeg -i input.mp4 -i sub.chi.srt -c copy -c:s mov_text -metadata:s:s:0 language=chi output.mp4
# 双语双轨(来源 5 命令)
ffmpeg -i input.mp4 -i sub.en.srt -i sub.chi.srt -map 0 -map 1 -map 2 -c copy -c:s mov_text \
       -metadata:s:s:0 language=eng -metadata:s:s:1 language=chi output_eng_chi.mp4
# MKV:字幕流原样塞入,连 mov_text 转码都不需要
ffmpeg -i input.mkv -i sub.srt -c copy -c:s srt output.mkv     # 或 -c:s copy(若输入已有字幕流)
# 校验/回取
ffprobe -v error -show_entries stream=index,codec_name,codec_type -of default=noprint_wrappers=1 output.mp4
ffmpeg -i output.mp4 -map 0:s:0 extracted.srt

📖 来源 5(提取转述):软字幕"can be toggled on or off during playback",硬字幕"burned into the video... cannot be removed afterward";SRT 只支持 <b>/<i>/<u>/<font> 简单标记,全样式要转 ASS。
✅ 本机实测:-c copy -c:s mov_text 封装 0.133 s、文件仅 +644 字节(对比硬字幕 0.886 s 重编码,快 6.7×);ffprobe 确认新增 index=2, codec_name=mov_text, TAG:language=chi;-map 0:s:0 往返提取出的 SRT 与原文逐字一致(中文无损)。
决策一句话:给万人看的成片/社交媒体 → 硬字幕;自留/自订/要双语切换 → 软字幕(MKV 优先)。

R8 · 批处理配方:for 循环(串行,最稳)

# bash:双引号包住 "$f" 是生死线;${f%.mp4} 去扩展名
mkdir -p out
for f in *.mp4; do
  ffmpeg -y -hide_banner -loglevel error -i "$f" \
         -c:v libx264 -preset veryfast -crf 28 -c:a copy "out/${f%.mp4}_c28.mp4" \
    || echo "FAILED: $f"
done
# Windows cmd
for %%f in (*.mov) do ffmpeg -i "%%f" "%%~nf.mp4"

✅ 本机实测:三个文件(episode 1.mp4、episode 2.mp4、第 3 集.mp4——含空格与中文)循环转码 3/3 成功,输出名/中文完好;带 -y 幂等可重跑。
⚠️ 覆盖语义与退出码(本次实测最大的意外收获):

R9 · 并行批处理:xargs -P(配方的保守并行)

📖 来源 7(gist 原文命令,NVENC 双会话场景):

$ find Videos/ -type f -name \*.avi -print | sed 's/.avi$//' |\
  xargs -n 1 -I@ -P 2 ffmpeg -i "@.avi" -c:a aac -c:v hevc_nvenc "@.mp4"

📖 来源 7(原文):"The noteworthy part here is the -P 2 to xargs, which starts up to two processes in parallel."
为什么是 -P 2 而不是 -P $(nproc):单个 libx264 编码进程本身已吃满多核,N 个全速进程并发会超订 CPU 并打爆磁盘 I/O;并行收益主要出现在弱多线程编码器(VP9/部分 AV1 配置)、NVENC 双会话上限、或 I/O 轻的短任务。需要抢吞吐时可给每个进程加 -threads N 分核。
✅ 本机实测:3 个 10 s 文件 find | xargs -n1 -I@ -P 2 转码 1.343 s 完成,输出文件名含空格/中文均正确(-I@ 按行替换,天然容忍空格;文件名含换行的极端情况应改用 -print0 | xargs -0)。
📖 来源 1(原文,同批一致性):"If you are encoding a set of videos that are similar, apply the same settings to all the videos: this will ensure that they will all have similar quality."——批量转码保持同一 CRF/preset 正是为此。

R10 · 预检配方:先编 30 秒看看

📖 来源 1(原文):"Encode a random section instead of the whole video with the -ss and -t/-to options to quickly get a general idea of what the output will look like."

ffmpeg -ss 00:05:00 -t 30 -i input -c:v libx264 -crf 23 -preset slow preview.mp4

(本会话所有实测均由此法先行——全部实验时长 ≤4 s/文件,几分钟跑完全部验证。)


五、来源关键数据与引述补遗

  1. slhck 的 CRF 原理(来源 3,原文):"Constant Rate Factor at CRF=18 will increase the QP to, say, 20, for high motion frames (compressing them more) and lower it down to 16 for low motion parts";动感知冗余的根据——"high motion 'masks' the presence of compression artifacts like blocking"。所以 CRF ≠ CQP:CRF 省下的比特花在人眼看得见的地方。同文并反对用 PSNR/SSIM 评质量:"More perceptually-based metrics like VQM or VMAF are better choices."
  2. slhck 的模式决策表(来源 4,原文节录):"1. Archival — CRF that gives you the quality you want. 2. Streaming — Two-pass CRF or ABR with VBV-constained bitrate. 3. Live Streaming — One-pass CRF or ABR with VBV-constained bitrate, or CBR if you can waste bits. 4. Encoding for Devices — Two-pass ABR, typically." 以及对网络教程的批评——"the most simple solution (just specifying bitrate) is one that isn't recommended at all, but the Web keeps propagating code examples using this method."
  3. ABR 单遍为什么烂(来源 4,原文):"Avoid using this mode! One of the main x264 developers himself says you should never use it."(编码器不知前路,开头码率乱飘。)
  4. Mux 的经验数字(来源 6,页面原句/提取数字):veryslow 比 fast 慢 5–10× 但同 CRF 小 10–20%;1080p→720p 缩尺寸省 50–60%;音频约占 5–10%;逐代重编码有代际损失——"each compression pass introduces additional quality loss (generation loss)"。
  5. x265 的两遍写法不同(来源 4,原文):pass 选项要放进私有参数——-x265-params pass=1:vbv-maxrate=1000:vbv-bufsize=2000 -f null /dev/null,第二遍 pass=2。

六、实测声明与偏差记录(诚实清单)

#文献声明本机实测结果判定
1CRF ±6 ≈ 体积减半/翻倍(来源 1/3)23→28 = −48.7%吻合
2preset 越慢体积越小ultrafast 8.93 → veryslow 3.28 MiB 单调下降(veryfast 3.37 例外,已知现象)基本吻合(有已知反常)
3medium→slow 时间 +40%(官方 FAQ)实测 +64%(0.885→1.448 s,短素材波动大)方向一致,幅度偏高
4两遍可命中目标体积目标 1 MiB → 0.978 MiB(−2.2%)吻合(偏小,不超标)
5软字幕秒级、硬字幕需重编码0.133 s vs 0.886 s,+644 字节吻合
6-movflags +faststart 前移 moov偏移 6,159,200 → 36吻合(字节级)
7x265 同质量省 ~50%(Mux)合成素材上 crf28 比 x264 crf23 小 31%方向一致(CRF 跨编码器不可比,数值不矛盾)
8(文献未载)失败必非零退出码拒绝覆盖时 exit=0(9.0.2 实测)文献假设被推翻,批处理须防
9(文献未载)AV1 crf30 应更省libsvtav1 crf30 = 5.41 MiB,反而大于 x264 crf23合成素材+默认参数下不成立,如实记录

复现说明:全部实验在会话内以真实命令运行(生成素材 testsrc2=size=1280x720:rate=30:duration=10 + sine,度量用 time 关键字与 ls -l 字节数,截图用 -ss 2 -frames:v 1 抽帧目检),原始输出已在会话记录中。


七、这次学到什么

  1. 先把"场景"问清楚,参数自己就定了:存档/点播/直播/设备四选一(slhck 决策表),比背 20 个参数更防错。ffmpeg 教程最大的噪声源就是拿 ABR 单遍当万能药。
  2. "公式 + 余量"优于"精确命中":8192 vs 8388.608 之争的本质是工程余量;x264 不填位流的特性让目标体积天然偏小 1–3%,写脚本时应预期"命中±3%"而非精确值。
  3. 字幕是一道"软硬"单选题,决策变量只有可移除性与播放器覆盖面;中文字幕的额外一维是字体/编码——UTF-8 SRT + force_style 指定 CJK 字体是 Windows 上的可靠组合。
  4. 批处理的第一性风险不在转码,在文件系统:引号、覆盖、退出码、并行度。本次实测抓到的"拒绝覆盖却 exit=0"证明:每个"理所当然"的平台行为都值得一条 10 秒的对照实验。
  5. 验证要落到最小可观测证据:字节序(faststart)、抽帧(烧录)、往返 diff(无损)、字节数(体积命中)——用仪器思维替代肉眼播放器,是 CLI 工具配方工程化的通用方法论。

附录 A · 本次全部实测命令(可整段复现)

# 0) 环境:ffmpeg 9.0.2-full_build-www.gyan.dev / Win11 / nproc=24
mkdir -p /tmp/ffrecipe && cd /tmp/ffrecipe
ffmpeg -y -f lavfi -i "testsrc2=size=1280x720:rate=30:duration=10" -f lavfi -i "sine=frequency=440:duration=10" \
  -c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p -c:a aac -b:a 128k src.mp4   # 6,171,001 B
# 1) CRF 阶梯
for c in 18 23 28 33; do time ffmpeg -y -i src.mp4 -c:v libx264 -preset medium -crf $c -c:a copy crf$c.mp4; done
# 2) preset 阶梯 @crf23:ultrafast/veryfast/medium/slow/veryslow(命令同上换 -preset)
# 3) 两遍目标 1 MiB:-b:v 710k -pass 1/-pass 2 -passlogfile /tmp/ffrecipe/pl
# 4) 硬字幕:-vf "subtitles=test.srt:force_style='FontName=Microsoft YaHei,FontSize=20'";抽帧目检
ffmpeg -ss 2 -i hard.mp4 -frames:v 1 frame_hard.png
# 5) 软字幕:-c copy -c:s mov_text -metadata:s:s:0 language=chi;往返:-map 0:s:0 提取 diff
# 6) 批处理:for 循环 + 无 -y 对照 + find|xargs -P 2;退出码逐一 echo $?
# 7) faststart:-c copy -movflags +faststart 后 od -A d -c 对比 moov/mdat 偏移

附录 B · 来源链接汇总

← 资料库今日播报 →