要約
- 手軽に対策するには
-map 0
を指定して全ての stream を出力 - 動画ファイルは program と stream で構成される構造
- 現時点 (2024-09-02) では、FFmpeg は入力ファイルの program 構造を完全に複製不能
- stream に含まれる次についてはこの記事では扱わないので、またの機会に解説:
- metadata
- packet, frame の PTS time
手軽な対策のコマンド
ffmpeg \
-i <入力ファイル名> \
-map 0 \
-c copy \
<出力ファイル名>
前提知識: 動画ファイルの構造
- 1 つの動画ファイルは複数の program を含むことが可能
- 1 つの program は複数の stream を含むことが可能
- program は stream を含まないことが可能
- 1 つの動画ファイルは program に含まれない stream を含むことが可能
- 1 つの動画ファイル内の stream はファイル内の全ての stream 間で順番を保持
確認方法
次のコマンドで出力される JSON データを解析することで確認可能:
ffprobe \
-show_entries program=program_num:stream=index \
-output_format json \
-loglevel repeat+fatal \
<動画ファイル名>
出力される JSON の例
{
"programs": [
{
"program_num": 23656,
"streams": [
{
"index": 1,
"side_data_list": [
{
}
]
},
{
"index": 2
},
{
"index": 3
},
{
"index": 4
},
{
"index": 5
},
{
"index": 6
}
]
},
{
"program_num": 0,
"streams": [
]
}
],
"stream_groups": [
],
"streams": [
{
"index": 0
},
{
"index": 1,
"side_data_list": [
{
}
]
},
{
"index": 2
},
{
"index": 3
},
{
"index": 4
},
{
"index": 5
},
{
"index": 6
}
]
}
JSON の root キーの streams
には、
program に含まれる stream と program に含まれない stream の両方が含まれることに注意
上記の JSON の場合、ファイル内の program と stream の構造は次の通り:
動画ファイル
├─ stream 0
├─ program 23656
│ ├─ stream 1
│ ├─ stream 2
│ ├─ stream 3
│ ├─ stream 4
│ ├─ stream 5
│ └─ stream 6
└─ program 0
FFmpeg はデフォルトでは入力ファイルの一部の stream のみ出力
FFmpeg はデフォルトでは:
- video, audio, 字幕の stream は入力ファイルから 1 つの stream のみ出力
- データや添付ファイルの stream は出力せず
4.1.1 Automatic stream selection | ffmpeg Documentation
ビデオ: 最高解像度の stream
オーディオ: 最も多くのチャンネルを持つ stream
字幕: 最初に見つかった字幕 stream ですが、注意点があります
出力形式のデフォルトの字幕エンコーダは
テキストベースまたは画像ベースのいずれかであり、
同じタイプの字幕ストリームのみが選択されます
同じタイプの複数のストリームが均等にレートする場合、
インデックスが最も低いストリームが選択されます
データまたは添付ファイルのストリームは自動的に選択されず、
-map を使用してのみ含めることができます
手軽な対策: -map
オプションの使用
入力ファイルが 1 つの場合は -map 0
で全ての stream を出力
Simple examples | Map – FFmpeg
-map 0
From input index #0 (the 1st input) select all streams.
FFmpeg は program と stream の構造を完全に複製不能
単純に -map 0
を指定すると、FFmpeg は入力ファイルの program 構造を維持せず、
新たに program_num
: 1 で program を作成し、
すべての stream をその program に含めるように動作する模様:
#4525 (Multi-program structure of input is not preserved in MPEG-TS output) – FFmpeg
先ほどの JSON の例で説明すると、
-map 0
を指定した場合の出力ファイルの program と stream の構造は次の通り:
入力ファイル 出力ファイル
├─ stream 0 └─ program 1
├─ program 23656 ├─ 入力ファイルの stream 0
│ ├─ stream 1 ├─ 入力ファイルの stream 1
│ ├─ stream 2 ├─ 入力ファイルの stream 2
│ ├─ stream 3 ├─ 入力ファイルの stream 3
│ ├─ stream 4 ├─ 入力ファイルの stream 4
│ ├─ stream 5 ├─ 入力ファイルの stream 5
│ └─ stream 6 └─ 入力ファイルの stream 6
└─ program 0
program の構造を維持するためには -program
オプションを使い、
program_num
と、その program に含める stream の index を指定する必要あり
参考:
FFMPEG - build transport stream with multiple programs - Video Production Stack Exchange
コマンドの例:
ffmpeg \
-i <入力ファイル名> \
-map 0:0 \
-map p:23656 \
-program program_num=23656:st=1:st=2:st=3:st=4:st=5:st=6 \
-c copy \
<出力ファイル名>
上記のコマンドを実行した場合の出力ファイルの program と stream の構造は次の通り:
入力ファイル 出力ファイル
├─ stream 0 ├─ program 23656
├─ program 23656 │ ├─ 入力ファイルの stream 1
│ ├─ stream 1 │ ├─ 入力ファイルの stream 2
│ ├─ stream 2 │ ├─ 入力ファイルの stream 3
│ ├─ stream 3 │ ├─ 入力ファイルの stream 4
│ ├─ stream 4 │ ├─ 入力ファイルの stream 5
│ ├─ stream 5 │ └─ 入力ファイルの stream 6
│ └─ stream 6 └─ 入力ファイルの stream 0
└─ program 0
上記の対応を行っても、次の内容は維持することは不可能:
- stream を含まない program
- stream の順序
なお、この他に metadata という情報や、
stream 内の各 packet, frame の PTS time に関しても見ておく必要があるが、
この記事では扱わないので、またの機会に解説
stream を含まない program
FFmpeg の -program
オプションで作成不能であるため
stream の順序
FFmpeg の -program
オプションを使用した場合、
stream の順序はコマンドのオプションで指定した順にならないため
-program
オプションを使用しなければ stream の順序は -map で指定した順
Order
The order of -map options is important:
- -map order determines the stream order in the output(s).
- Mapping is applied in order. This is useful when using negative mapping.
Examples
Tip:
You can add -c copy to many of these examples to enable stream copy mode.
This is useful if you want to mux only and avoid encoding.
-map 0
を設定した場合 -copy_unknown
は不要
検証したところ、-map 0
を設定した場合、
-copy_unknown
を設定しなくても
FFMpeg がサポートしていない codec
の stream を含む全ての stream が出力されることを確認済
念のため、-map 0 -copy_unknown
を設定しても動作に問題なし
5.11 Advanced options | ffmpeg Documentation
-copy_unknown
Allow input streams with unknown type to be copied instead of failing
if copying such streams is attempted.