分割録画した動画やイベント映像は、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 行ずつ書きます。シングルクオートでパスを囲み、各ファイルのフルパスまたは相対パス(リストファイルから見た)を指定します。