FFmpegで動画を結合する

ファイルリストを使用する方法

結合したい動画ファイルのリストを作成します。たとえば、filelist.txtというテキストファイルに以下のように書きます。

file 'input1.mp4'
file 'input2.mp4'
file 'input2.mp4'

次に、以下のコマンドを実行します。

ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

スクリプト化

ファイル作ったり手間なので、自動でファイル生成して、ffmpeg実行するスクリプトをつくりました。ついでに前後の秒数指定でトリミングできます。

例)
input1.mp4の先頭5秒トリミング
input2.mp4の後尾3秒トリミング
input3.mp4
この3つを結合して、output.mp4を出力

sh ./concat.sh input1.mp4:h5000 input2.mp4:t3000 input3.mp4 output.mp4

concat.sh のコード

#!/bin/bash

# 引数のチェック
if [ "$#" -lt 2 ]; then
  echo "Usage: $0 <input1[:hN|tN]> <input2[:hN|tN]> [<input3[:hN|tN]> ...] <output>"
  exit 1
fi

# 出力ファイル名を取得
output=${!#}

# 一時的なファイルリストを作成
filelist="filelist.txt"
tempfiles="tempfiles.txt"

# filelist.txtとtempfiles.txtをクリア
> $filelist
> $tempfiles

# 入力ファイルを処理し、一時ファイルリストを作成
for ((i=1; i<=$#-1; i++)); do
  input=${!i}
  
  # カットオプションの解析
  if [[ "$input" == *:h* ]]; then
    basefile=$(echo "$input" | cut -d ':' -f 1)
    cut_time=$(echo "$input" | sed -n 's/.*:h\([0-9]*\).*/\1/p')
    ext="${basefile##*.}"
    filename="${basefile%.*}"
    temp_file="${filename}h${cut_time}.${ext}"
    ffmpeg -ss 0.${cut_time} -i "$basefile" -c copy "$temp_file"
    echo "file '$temp_file'" >> $filelist
    echo "$temp_file" >> $tempfiles
  elif [[ "$input" == *:t* ]]; then
    basefile=$(echo "$input" | cut -d ':' -f 1)
    cut_time=$(echo "$input" | sed -n 's/.*:t\([0-9]*\).*/\1/p')
    duration=$(ffmpeg -i "$basefile" 2>&1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,//)
    IFS=: read -r hour minute second <<< "$duration"
    total_seconds=$(echo "$hour*3600 + $minute*60 + $second" | bc)
    end_time=$(echo "$total_seconds - $cut_time / 1000" | bc)
    ext="${basefile##*.}"
    filename="${basefile%.*}"
    temp_file="${filename}t${cut_time}.${ext}"
    ffmpeg -i "$basefile" -t "$end_time" -c copy "$temp_file"
    echo "file '$temp_file'" >> $filelist
    echo "$temp_file" >> $tempfiles
  else
    echo "file '$input'" >> $filelist
  fi
done

# filelistの内容を表示してデバッグ
echo "Created file list:"
cat $filelist

# FFmpegでファイルを結合
ffmpeg -f concat -safe 0 -i $filelist -c copy $output

# 一時ファイルを削除
rm $filelist
while IFS= read -r tempfile; do
  rm "$tempfile"
done < $tempfiles
rm $tempfiles


この記事が気に入ったらサポートをしてみませんか?