简体中文
ffmpeg 使用教程

ffmpeg 教程

一、创建 filelist.txt 文件

推荐使用命令行工具直接生成列表文件,这样能避免文本编辑器可能引入的格式问题。具体操作如下:

单目录生成

  1. 打开终端,进入视频所在的目录。
  2. 执行下面的命令生成文件列表:
printf "file '%s'\n" *.mp4 > filelist.txt
  • 要是你的视频文件名包含特殊字符(像空格、单引号等),可以使用这个更安全的命令:
for f in *.mp4; do echo "file '$f'" >> filelist.txt; done

多目录生成

  1. 打开终端,进入视频所在的根目录。
  2. 执行下面的命令将生成每个子目录文件列表:
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
文章在技术分类中;
0
0
0
0