批量处理与常见问题排错
本教程共 32 篇 · 第 32 篇 · 更新于 2026-08-09 · 约 8 分钟阅读
本节目标:会写简单的批量转码脚本;遇到报错时能从错误信息定位原因,自己解决最常见的十几类问题。
教程最后一章,讲两件实用的事:批量处理和排错。单个命令查着文档能写出来不算掌握,能让一批文件自动跑、能在报错时自己救自己,才算真正上手。
一、批量处理
有一堆 .mov 文件要全转成 MP4,不能一个一个敲。用脚本循环。
Windows PowerShell
把当前目录下所有 .mov 转成 H.264/AAC 的 MP4:
Get-ChildItem -Filter *.mov | ForEach-Object {
$out = [System.IO.Path]::ChangeExtension($_.FullName, ".mp4")
ffmpeg -i $_.FullName -c:v libx264 -crf 23 -c:a aac $out
}
批量缩放成 720p:
Get-ChildItem -Filter *.mp4 | ForEach-Object {
ffmpeg -i $_.FullName -vf "scale=-2:720,format=yuv420p" -c:a copy "out_$($_.Name)"
}
macOS / Linux(Bash)
for f in *.mov; do
ffmpeg -i "$f" -c:v libx264 -crf 23 -c:a aac "${f%.mov}.mp4"
done
批量提取音频:
for f in *.mp4; do
ffmpeg -i "$f" -vn -c:a libmp3lame -q:a 2 "${f%.mp4}.mp3"
done
批量处理的几个建议
- 先拿一个文件试:确认参数无误再跑批,避免浪费几小时才发现参数错了。
- 加
-hide_banner -loglevel error:减少输出,只看错误。 - 用
-y自动覆盖或不加-y自动跳过,根据需要选择。 - 失败不中断:一个文件出错不要让整个批次停下来。Bash 里正常情况下 ffmpeg 失败后循环继续;PowerShell 里可以加
$ErrorActionPreference = "Continue"。 - 输出到单独目录:避免源文件和输出混在一起。
二、排错的基本思路
FFmpeg 报错时不要慌。报错信息的最后几行才是关键原因。往上滚找到第一个 Error、Invalid、Unknown、Unable 开头的行,比盯着满屏日志有用得多。
增加信息详细度:
ffmpeg -v error -i input.mp4 ... # 只显示错误
ffmpeg -v debug -i input.mp4 ... # 最详细(用于排查棘手问题)
下面是最常见的报错和修法。
三、“Unknown encoder ‘xxx’”
Unknown encoder 'libx265'
编码器名字写错,或者你的 FFmpeg 编译时没带这个编码器。
排查:
ffmpeg -encoders | findstr x265 # Windows
ffmpeg -encoders | grep x265 # macOS/Linux
没有输出说明不支持。解决方法:
- 确认名字:H.265 软件编码器是
libx265,不是h265(h265只是解码器)。 - 换一个支持的编码器(比如用
hevc_nvenc硬编代替)。 - 安装完整版 FFmpeg(gyan.dev full 版本或自己编译带
--enable-libx265)。
四、“width not divisible by 2” / “height not divisible by 2”
height not divisible by 2 (853x481)
H.264/H.265 默认要求宽高是偶数(YUV 4:2:0 以 2×2 块为单位)。源分辨率是奇数就会报。
修法:用 scale 保证偶数:
ffmpeg -i input.mp4 -vf "scale=-2:720" output.mp4
-2 表示自动按比例计算,并取最接近的偶数。也可以用 scale=trunc(iw/2)*2:trunc(ih/2)*2 强制把原尺寸变成偶数。
五、“Stream map ‘0:v:0’ matches no streams”
Stream map '0:a:0' matches no streams.
你 -map 了一个不存在的流。比如文件只有视频没有音频,却 map 了音频。
排查:先看文件里有什么流:
ffprobe input.mp4
或者:
ffmpeg -i input.mp4
输出里看 Stream #0:0、Stream #0:1 分别是什么类型。有哪些流就 map 哪些,或者加可选标记 0:a:0?(问号表示”有就选,没有就跳过”):
ffmpeg -i input.mp4 -map 0:v:0 -map 0:a:0? -c:v libx264 output.mp4
六、“Invalid data found when processing input”
[mov,mp4,m4a,3gp,3g2,mj2 @ ...] moov atom not found
Invalid data found when processing input
文件损坏、没下完、格式和后缀名不一致,或者根本不是音视频文件。
排查:
ffprobe input.mp4
看 ffprobe 能不能识别。文件是坏的就重新获取;如果是 FLV 改名为 MP4 这类情况,要么用正确后缀,要么转封装:
ffmpeg -i input.flv -c copy output.mp4
七、“Unsupported codec” 或播放器只有声音没有画面
视频流能解,但封装到 MP4 时播放器不认。常见于源是 yuv444p 像素格式(H.264 只支持部分 profile)或者用了 MP4 不支持的编码(如 VP9/Opus 在旧播放器上)。
修法:转成通用像素格式和编码器:
ffmpeg -i input.mp4 -c:v libx264 -pix_fmt yuv420p -c:a aac output.mp4
-pix_fmt yuv420p 是兼容所有 H.264 播放器的像素格式。
八、音画不同步
原因有多种,常见解法:
- 容器时间戳问题:转封装时加
-fflags +genpts重新生成时间戳:
ffmpeg -fflags +genpts -i input.mkv -c copy output.mp4
- 录制时丢帧导致:重编码时加
-vsync cfr强制恒定帧率:
ffmpeg -i input.mp4 -c:v libx264 -vsync cfr -c:a aac output.mp4
- 音频采样率不匹配:统一成 48000:
ffmpeg -i input.mp4 -ar 48000 output.mp4
- 从
-ss截取后不同步:把-ss放在-i前面(快速定位但可能不精确),或者放在-i后面(精确但慢),并配合-avoid_negative_ts make_zero。
九、“Too many packets buffered” / 拼接报错
用 concat filter 拼接时,各段参数不一致导致:
Input link in1:v0 parameters (size 1280x720) do not match the corresponding output link
拼接前先把所有片段统一成相同分辨率、帧率、像素格式、采样率、声道数:
ffmpeg -i clip1.mp4 -i clip2.mp4 -filter_complex \
"[0:v]scale=1280:720,fps=30,format=yuv420p[v0]; \
[1:v]scale=1280:720,fps=30,format=yuv420p[v1]; \
[0:a]aresample=48000[a0];[1:a]aresample=48000[a1]; \
[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" output.mp4
或者用 concat demuxer(同编码的片段不需要重编码,见第 14 章)。
十、编码太慢 / 速度上不去
- 换快 preset:
-preset veryfast或ultrafast。 - 用硬件编码:
-c:v h264_nvenc/h264_qsv/h264_videotoolbox。 - 加线程:x264/x265 默认会用满 CPU,不用手动设;硬编码器线程数有限,多文件并行比单文件多线程更有效。
- 检查输入是不是在慢速硬盘:把文件拷到本地 SSD 再处理。
- 减少滤镜复杂度:10-bit、高精度缩放、多遍降噪都很吃 CPU。
十一、编码后体积反而变大
CRF 设太低(比如 10)或者用了 CBR 高码率,都会导致重新编码后更大。记住:
- 不指定 CRF/码率时,x264 有默认值,不一定和源相当。
-c copy不会变小,它不重编码。- 已经是高压缩有损格式的源,再怎么转也不会变小,画质只会更差。
原则:要小体积,用 CRF 22–26 + slow preset;要精确体积,用 two-pass。
十二、宏块和运动向量可视化(调试用)
想直观看到编码器是怎么划分画面的,可以用 codecview 把运动向量画出来:
ffplay -flags2 +export_mvs input.mp4 -vf codecview=mv=pf+bf+bb
pf 是 P 帧前向运动向量,bf/bb 是 B 帧前向/后向。这个功能主要用于视频编码学习和分析,日常用不到,但在理解”为什么这段画面糊”时很直观。
十三、终极排查命令
当你完全不知道一个文件什么情况:
ffprobe -v error -show_format -show_streams -print_format json input.mp4
输出 JSON,里面有所有流的编码、分辨率、帧率、码率、采样率、时长、元数据。把这段输出保存下来,查文档或求助时贴给别人,比描述”它就是播不了”有用得多。
Tip排错三步法:
- 读最后一条 Error 行,别被满屏 warning 吓住。
- 用 ffprobe 看输入,确认源文件的真实参数。
- 最小化命令:去掉滤镜、去掉
-map、只转封装试能不能跑,再逐个加回参数定位问题。90% 的问题都是参数写错、文件损坏、编码器不支持这三类。剩下 10% 再去搜错误信息原文,基本都能找到答案。
到这里,32 章的 FFmpeg 命令行知识就学完了。从容器编码到滤镜流媒体,核心概念已经覆盖。FFmpeg 的参数多到没人能全记住,但你已经知道遇到问题该查什么、该怎么试。剩下的就是多用,命令行工具是肌肉记忆,用多了就熟了。