请稍侯

ffmpeg 视频处理

13 May 2024

ffmpeg 视频处理

单视频重复拼接
使用ffmpeg 将当前目录下的 aaa.mp4 文件重复拼接10次后生成一个长视频输出到前前目录

ffmpeg -f concat -safe 0 -i <(for i in {1..10}; do echo "file '$PWD/aaa.mp4'"; done) -c copy ./output.mp4

filelist=$(mktemp) && for i in {1..10}; do echo "file '$PWD/aaa.mp4'"; done > "$filelist" && ffmpeg -f concat -safe 0 -i "$filelist" -c copy "./output.mp4" && rm "$filelist"

多视频拼接
使用ffmpeg 将当前目录下的所有 mp4 文件拼接生成一个长视频 all.mp4 输出到前目录

ffmpeg -f concat -safe 0 -i <(find "$(pwd)" -name "*.mp4" -printf "file '%p'\n") -c copy ./all.mp4

若终端不支持进程替换语法 <(),可以使用以下写法:

# 1.生成包含文件路径的文本文件
find "$(pwd)" -name "*.mp4" -printf "file '%p'\n" > filelist.txt
# 2.使用 ffmpeg 命令拼接视频
ffmpeg -f concat -safe 0 -i filelist.txt -c copy ./all.mp4

使用分号 ; 将两个命令连接起来写在一行里,以便在终端中直接执行

find "$(pwd)" -name "*.mp4" -printf "file '%p'\n" > filelist.txt ; ffmpeg -f concat -safe 0 -i filelist.txt -c copy ./all.mp4

find "$(pwd)" -maxdepth 1 -name "*.mp4" -printf "file '%p'\n" > filelist.txt ; ffmpeg -f concat -safe 0 -i filelist.txt -c copy "./all_$(basename $(pwd)).mp4"; rm filelist.txt

批量拼接
将当前目录下的每个子文件夹中的 mp4 文件拼接生成一个长视频输出到相对应的子文件夹中:

find "$(pwd)" -mindepth 1 -type d \( -name "@eaDir" -o -name ".*" \) -prune -exec sh -c '
  dir=$(dirname "{}")
  [ "$dir" != "$(pwd)" ] || exit
  echo "====" cd "$dir"
  cd "$dir" || exit

  find . -maxdepth 1 -name "*.mp4" -printf "file '\''%p'\''\n" > filelist.txt
  echo ffmpeg -f concat -safe 0 -i filelist.txt -c copy "all_$(basename "$dir").mp4"
  ffmpeg -f concat -safe 0 -i filelist.txt -c copy "all_$(basename "$dir").mp4"
  rm filelist.txt
' \;

批量移动生成后的视频
将以上所有生成在子目录中的 "all_$(basename "$dir").mp4" 移动到当前目录

# 在 find 命令的 -exec 选项中,由于子进程的原因,无法直接访问外部的 base_dir 变量。这就导致了 base_dir 在子进程中为空。为了解决这个问题,您可以将 base_dir 作为环境变量传递给子进程。
base_dir=$(pwd); find "$base_dir" -mindepth 1 -type d \( -name "@eaDir" -o -name ".*" \) -prune -exec sh -c '
  dir=$(dirname "{}")
  base_dir="$2"
  [ "$dir" != "$1" ] || exit
  cd "$dir" || exit
  echo ==== mv  "all_$(basename "$dir").mp4" "$base_dir"
  mv  "all_$(basename "$dir").mp4" "$base_dir"
' sh "$base_dir" "$base_dir" \;
# 使用 sh "$base_dir" "$base_dir" 在 -exec 选项中传递了两个参数给子进程。第一个参数 $1 是子进程中的 dir 变量,用于检查是否与当前目录相同。第二个参数 $2 是子进程中的 base_dir 变量,用于输出。

解决因输入视频不同编码拼接后的播放问题,可以尝试用以下命令:

ffmpeg -f concat -safe 0 -i filelist.txt -c:v libx264 -crf 23 -c:a aac -b:a 192k "./all_$(basename $(pwd)).mp4"

删除当前目录中所有文件名中的”冒死上传B站最全AI人工智能课程_“字符

for f in *; do mv "$f" "${f//冒死上传B站最全AI人工智能课程_/}"; done