分割録画した動画やイベント映像は、FFmpeg で順番につないで1本にできます。やり方を間違えると、不要な再エンコードで何十分も待たされたり、つなぎ目で音ズレが出たりします。FFmpeg には目的の異なる2つの結合方法があり、素材が同一コーデックかどうかで選びます。同一なら再エンコードなしの concat demuxer で数秒、フォーマットがバラバラなら concat filter で吸収します。

2つのconcatアプローチの比較

比較項目 concat demuxer concat filter
速度 高速(再エンコードなし) 遅い(再エンコードあり)
互換性要件 同一コーデック・フォーマットが必要 コーデックが違っても結合可能(解像度・SARは揃える)
入力ファイル数 何ファイルでも対応 入力ファイル数分の -i が必要
ファイルリスト テキストファイル(list.txt)が必要 不要
コマンドの複雑さ シンプル filter_complex 記法が必要

concat demuxer(高速・同一フォーマット向け)

概要

concat demuxerは、テキストファイルに列挙したファイルを順番に連結する方法です。再エンコードしないため高速です。

ファイルリスト(list.txt)の作成

concat demuxerには専用のテキストファイルが必要です。list.txt を以下の形式で作成します。

# list.txt の例(コメント行は # で始める)
file 'part1.mp4'
file 'part2.mp4'
file 'part3.mp4'

Linuxでコマンドラインから作成する場合。

printf "file 'part1.mp4'\nfile 'part2.mp4'\nfile 'part3.mp4'\n" > list.txt

Windowsコマンドプロンプトから作成する場合。

(echo file 'part1.mp4' & echo file 'part2.mp4' & echo file 'part3.mp4') > list.txt

concat demuxerの実行コマンド

ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
オプション 意味
-f concat concat demuxerを使用
-safe 0 ファイルパスの安全チェックを無効化(絶対パスや特殊文字を含む場合に必要)
-i list.txt ファイルリストを入力として指定
-c copy 再エンコードなし(ストリームコピー)

concat demuxer使用上の注意

  • すべてのファイルが同一のコーデック、解像度、フレームレートである必要があります
  • フォーマットが異なると映像・音声の同期がズレたり、エラーが発生することがあります
  • -safe 0 を省略すると、絶対パスや、スペース・日本語などを含むファイル名がエラー(Unsafe file name)になります

concat filter(柔軟・異フォーマット対応)

概要

filter_complex の concat フィルタは、コーデックやコンテナが異なるファイルでも結合できます。ただし解像度とSAR(画素の縦横比)は揃っている必要があり、違う場合は事前に揃えます(後述)。再エンコードが発生しますが、汎用性の高い方法です。

基本コマンド(2ファイルの結合)

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

filter_complex 記法の解説

[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]
部分 意味
[0:v][0:a] 1番目の入力(index 0)の映像・音声ストリーム
[1:v][1:a] 2番目の入力(index 1)の映像・音声ストリーム
concat=n=2 2つのセグメントを結合(ファイル数に合わせて変更)
v=1:a=1 映像1ストリーム・音声1ストリームを出力
[outv][outa] 出力ラベル(-map で参照)

3ファイルの結合

ffmpeg -i input1.mp4 -i input2.mp4 -i input.mkv -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

n=3 にしてすべてのストリームペアを列挙します。

コーデックを指定して結合

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" -c:v libx264 -crf 23 -c:a aac output.mp4

解像度・フレームレートの統一

concat filterは、解像度やSARが異なるとエラーで止まります(フレームレートが異なる場合はエラーにならず、可変フレームレートで出力されます)。事前にscaleフィルタとsetsarフィルタで解像度とSARを、fpsフィルタでフレームレートを統一してください。

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v]scale=1280:720,setsar=1,fps=30[v0];[1:v]scale=1280:720,setsar=1,fps=30[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" -c:v libx264 -crf 23 -c:a aac output.mp4
追加フィルタ 目的
scale=1280:720 解像度を統一
setsar=1 SAR(画素の縦横比)を1:1に統一(縦横比の違う素材は引き伸ばされます)
fps=30 フレームレートを統一

方法の選び方まとめ

concat demuxerを選ぶべきケース:

  • すべてのファイルが同じコーデックと解像度を持っている
  • ファイルが多数あり、再エンコードなしで素早く連結したい
  • 録画ファイルの分割データを結合するなど、均質なデータを扱う

concat filterを選ぶべきケース:

  • ファイルのコーデックや解像度がバラバラ(解像度は scale で揃えてから結合)
  • スクリプトで動的にファイルを指定したい(リストファイル不要)
  • トリミング結果を直接結合したい

よくあるエラーと対処法

DTS ... out of order エラー

タイムスタンプが不連続なファイルを concat demuxer で結合した際に発生します。-c copy を -c:v libx264 -c:a aac に変更してください。

音声がずれる

フレームレートや音声サンプルレートが異なる場合に発生します。concat filterを使い、事前にfpsフィルタとaresampleフィルタで統一してください。

特定のファイルがスキップされる

list.txtのファイルパスにスペースや特殊文字が含まれる場合、クォートが正しく処理されているか確認してください。

関連記事

よくある質問

concat は何種類あるの?

3 種類あります。(1) concat protocol(MPEG-TS や MPEG-PS など、バイト単位でつなげられる形式向けのバイト連結)、(2) concat demuxer(任意コンテナ、リストファイル経由、-c copy 可)、(3) concat filter(再エンコード必須。つなぐだけで、トランジションには xfade / acrossfade を使います)です。MP4 の結合には demuxer か filter を使います。

異なる解像度の動画を結合したい

concat filter が必要です。[0:v]scale=1920:1080,setsar=1[v0];[1:v]scale=1920:1080,setsar=1[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a] のように、事前にスケールで解像度を揃え、setsar で SAR も揃えます。

結合後に音ズレする

VFR 動画が混ざっていることが典型的な原因です。事前に各動画を CFR に変換(-fps_mode cfr -r 30)してから concat してください。

結合時に黒画面が一瞬入る

タイムスタンプの不連続が原因です。再エンコードする concat filter に切り替えてください。-fflags +genpts は欠けたPTSを補うだけなので、この場合は効きません。

リストファイルの書式は?

file 'video1.mp4' を 1 行ずつ書きます。シングルクオートでパスを囲み、各ファイルのフルパスまたは相対パス(リストファイルから見た)を指定します。