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
この記事が気に入ったらサポートをしてみませんか?