首页 / FFmpeg 入门教程 / 批量处理与常见问题排错

FFmpeg 入门教程

批量处理与常见问题排错

本教程共 32 篇 · 第 32 篇 · 更新于 2026-08-09 · 约 8 分钟阅读

FFmpeg批量处理排错报错PowerShellBashFAQ

本节目标:会写简单的批量转码脚本;遇到报错时能从错误信息定位原因,自己解决最常见的十几类问题。

教程最后一章,讲两件实用的事:批量处理排错。单个命令查着文档能写出来不算掌握,能让一批文件自动跑、能在报错时自己救自己,才算真正上手。

一、批量处理

有一堆 .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

批量处理的几个建议

  1. 先拿一个文件试:确认参数无误再跑批,避免浪费几小时才发现参数错了。
  2. -hide_banner -loglevel error:减少输出,只看错误。
  3. -y 自动覆盖或不加 -y 自动跳过,根据需要选择。
  4. 失败不中断:一个文件出错不要让整个批次停下来。Bash 里正常情况下 ffmpeg 失败后循环继续;PowerShell 里可以加 $ErrorActionPreference = "Continue"
  5. 输出到单独目录:避免源文件和输出混在一起。

二、排错的基本思路

FFmpeg 报错时不要慌。报错信息的最后几行才是关键原因。往上滚找到第一个 ErrorInvalidUnknownUnable 开头的行,比盯着满屏日志有用得多。

增加信息详细度:

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

没有输出说明不支持。解决方法:

  1. 确认名字:H.265 软件编码器是 libx265,不是 h265h265 只是解码器)。
  2. 换一个支持的编码器(比如用 hevc_nvenc 硬编代替)。
  3. 安装完整版 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:0Stream #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 播放器的像素格式。

八、音画不同步

原因有多种,常见解法:

  1. 容器时间戳问题:转封装时加 -fflags +genpts 重新生成时间戳:
ffmpeg -fflags +genpts -i input.mkv -c copy output.mp4
  1. 录制时丢帧导致:重编码时加 -vsync cfr 强制恒定帧率:
ffmpeg -i input.mp4 -c:v libx264 -vsync cfr -c:a aac output.mp4
  1. 音频采样率不匹配:统一成 48000:
ffmpeg -i input.mp4 -ar 48000 output.mp4
  1. -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 章)。

十、编码太慢 / 速度上不去

  1. 换快 preset-preset veryfastultrafast
  2. 用硬件编码-c:v h264_nvenc / h264_qsv / h264_videotoolbox
  3. 加线程:x264/x265 默认会用满 CPU,不用手动设;硬编码器线程数有限,多文件并行比单文件多线程更有效。
  4. 检查输入是不是在慢速硬盘:把文件拷到本地 SSD 再处理。
  5. 减少滤镜复杂度: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

排错三步法:

  1. 读最后一条 Error 行,别被满屏 warning 吓住。
  2. 用 ffprobe 看输入,确认源文件的真实参数。
  3. 最小化命令:去掉滤镜、去掉 -map、只转封装试能不能跑,再逐个加回参数定位问题。

90% 的问题都是参数写错、文件损坏、编码器不支持这三类。剩下 10% 再去搜错误信息原文,基本都能找到答案。


到这里,32 章的 FFmpeg 命令行知识就学完了。从容器编码到滤镜流媒体,核心概念已经覆盖。FFmpeg 的参数多到没人能全记住,但你已经知道遇到问题该查什么、该怎么试。剩下的就是多用,命令行工具是肌肉记忆,用多了就熟了。

上一篇
硬件加速
下一篇
已经是最后一篇啦