
ffmpeg 教程
一、创建 filelist.txt 文件
推荐使用命令行工具直接生成列表文件,这样能避免文本编辑器可能引入的格式问题。具体操作如下:
单目录生成
- 打开终端,进入视频所在的目录。
- 执行下面的命令生成文件列表:
printf "file '%s'\n" *.mp4 > filelist.txt
- 要是你的视频文件名包含特殊字符(像空格、单引号等),可以使用这个更安全的命令:
for f in *.mp4; do echo "file '$f'" >> filelist.txt; done
多目录生成
- 打开终端,进入视频所在的根目录。
- 执行下面的命令将生成每个子目录文件列表:
for dir in 11.*; do
# 11.* 为目标目录的文件名前缀
if [ -d "$dir" ]; then
(
cd "$dir" || exit
mp4s=(*.mp4)
if [ -e "${mp4s[1]}" ]; then
printf "file '%s'\n" "${mp4s[@]}" > filelist.txt
echo "✅ Created filelist.txt in $dir"
# mp4 为文件扩展名格式;filelist.txt为生成的目录文件, 可按需调整。
else
echo "⚠️ Skipped $dir (no .mp4 files)"
# 跳过无.mp4文件的进程,确保过程不中断。
fi
)
fi
done
二、验证文件格式
生成文件后,可通过以下命令检查文件格式是否正确:
cat -e filelist.txt
正确的输出应该是这个样子:
file 'video1.mp4'
file 'video2.mp4'
file 'video3.mp4'
这里的 $ 符号代表换行符。如果看到 ^M$,就说明存在 Windows 风格的换行符(CRLF),需要进行转换。
三、转换文件格式(如果有需要)
若文件格式存在问题,可使用以下命令将换行符转换为 Unix 格式:
tr -d '\r' < filelist.txt > filelist_unix.txt
mv filelist_unix.txt filelist.txt
四、执行合并命令
单目录合并
对每个目录中的 filelist.txt 执行:
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4
并把输出文件命名为该目录名(如 11.29.23.mp4),保存在上级目录或原目录。
多目录合并
✅ 推荐方案:批量合并到上级目录
for dir in 11.*; do
if [ -d "$dir" ] && [ -f "$dir/filelist.txt" ]; then
# 检查 filelist.txt 是否非空
if [ -s "$dir/filelist.txt" ]; then
output_name="${dir}.mp4"
echo "🎥 Merging videos in $dir → $output_name"
ffmpeg -f concat -safe 0 -i "$dir/filelist.txt" -c copy "$output_name"
echo "✅ Done: $output_name"
else
echo "⚠️ Skipped $dir (filelist.txt is empty)"
fi
fi
done
合并后保存在各自子目录内
for dir in 11.*; do
if [ -d "$dir" ] && [ -f "$dir/filelist.txt" ]; then
if [ -s "$dir/filelist.txt" ]; then
echo "🎥 Merging videos in $dir"
ffmpeg -f concat -safe 0 -i "$dir/filelist.txt" -c copy "$dir/merged.mp4"
echo "✅ Done: $dir/merged.mp4"
else
echo "⚠️ Skipped $dir (empty filelist)"
fi
fi
done
✅ 最终建议命令(合并到上级目录 + 安全检查)
#!/bin/zsh
for dir in 11.*; do
if [ -d "$dir" ] && [ -f "$dir/filelist.txt" ]; then
if [ -s "$dir/filelist.txt" ]; then
output="${dir}.mp4"
echo "🎬 Processing $dir → $output"
ffmpeg -v quiet -stats -f concat -safe 0 -i "$dir/filelist.txt" -c copy "$output"
echo "✅ Completed: $output"
else
echo "⚠️ Skipping $dir: filelist.txt is empty"
fi
fi
done
echo "🎉 All done!"
-v quiet -stats:隐藏冗余日志,只显示进度条和关键信息- 适合长时间批量处理
📌 关键参数说明
| 参数 | 作用 |
|---|---|
-f concat | 使用 concat demuxer(按文本列表拼接) |
-safe 0 | 允许绝对路径或特殊字符(你的 file 'xxx.mp4' 是相对路径,但加了更安全) |
-c copy | 直接复制流,不重新编码(秒合,无损) |
-i filelist.txt | 输入文件列表 |
✅ 前提:所有
.mp4视频的编码格式、分辨率、帧率需一致,否则-c copy可能失败。如果不一致,需去掉-c copy并指定编码(会变慢)。
五、故障排除建议
- 检查视频文件所属目录下。
- 确认文件名中没有未闭合的单引号或其他特殊字符。
- 尝试手动创建一个简单的文件列表,比如只包含两个视频文件,测试基本功能是否正常。
- 文件顺序是否正确。
- TS格式文件合并常见问题。
目录问题
如执行异常,可尝试使用绝对路径。先获取当前目录的绝对路径:
pwd
假设输出是 /Users/yourname/Videos,那么文件列表应该写成这样:
file '/Users/yourname/Videos/video1.mp4'
file '/Users/yourname/Videos/video2.mp4'
- 要是视频文件不在同一目录,就需要使用完整的绝对路径。
特殊字符
对于包含特殊字符的文件名,可使用双引号和转义符:
for f in *.mp4; do echo "file \"$(printf "%q" "$f")\"" >> filelist.txt; done
文件顺序
filelist.txt 中的顺序 = 合并顺序。
如果你希望按文件名排序,生成 filelist.txt 时可改用:
printf "file '%s'\n" $(ls *.mp4 | sort -V) > filelist.txt
(sort -V 支持版本号排序,如 video1.mp4, video10.mp4)
空目录
脚本已通过 [ -s "$dir/filelist.txt" ] 判断是否为空,避免无效调用。
TS格式文件
当使用 FFmpeg 合并 TS 文件后出现音频丢失的问题,通常与流映射、编码器兼容性或合并方法有关。以下是可能的原因及解决方案:
1. 合并方法不正确
直接使用 cat 或简单的文件拼接会破坏音视频同步,导致音频丢失。正确方法是使用 FFmpeg 的 concat 协议或 concat 过滤器:
方案 1:使用 concat 协议(推荐)
创建一个文本文件 list.txt,列出所有 TS 文件:
file 'part1.ts'
file 'part2.ts'
file 'part3.ts'
然后执行合并:
ffmpeg -f concat -safe 0 -i list.txt -c copy output.ts
- 参数说明:
-f concat:指定使用 concat 协议。-safe 0:允许使用绝对路径或相对路径。-c copy:直接复制音视频流,不重新编码(速度快)。
2. 流映射问题
如果 TS 文件的音视频流索引不一致,FFmpeg 可能会忽略某些流。使用 -map 参数强制包含所有音视频流:
ffmpeg -f concat -safe 0 -i list.txt -map 0 -c copy output.ts
-map 0:映射输入文件中的所有流(音频+视频)。
3. 音频编码不兼容
如果原始 TS 文件的音频编码不同(如部分 AAC、部分 MP3),合并时可能导致音频丢失。此时需要重新编码音频:
ffmpeg -f concat -safe 0 -i list.txt -c:v copy -c:a aac output.mp4
-c:v copy:视频流直接复制。-c:a aac:音频重新编码为 AAC(兼容性更好)。
4. 检查原始 TS 文件的音频
使用以下命令确认每个 TS 文件是否包含音频流:
ffmpeg -i part1.ts
如果某个文件没有音频,合并后整体音频会中断。此时需要单独处理缺失音频的文件。
5. 使用 concat 过滤器(更灵活)
当 TS 文件格式差异较大时,concat 过滤器更可靠(但需要重新编码):
ffmpeg -i part1.ts -i part2.ts -i part3.ts \
-filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" -c:v libx264 -c:a aac output.mp4
- 参数说明:
concat=n=3:v=1:a=1:合并 3 个文件的视频和音频。-c:v libx264 -c:a aac:重新编码为 H.264+AAC。
6. 修复损坏的 TS 文件
如果 TS 文件本身损坏,可能导致音频丢失。尝试先修复单个文件:
ffmpeg -i corrupted.ts -c copy -bsf:v h264_mp4toannexb -f mpegts fixed.ts