- FFmpeg でカット編集をする際、カット位置のズレまたは再エンコードが必ず発生 (仕様)
- 多くの場合問題ないはず
- どちらを回避するかは FFmpeg に指定されたオプションの内容から
ユーザーの意図に沿った方を適切に決定するような仕様になっているため
- どちらを回避するかは FFmpeg に指定されたオプションの内容から
- この記事は厳密な部分が気になる人向け
- この記事は上の方ほど要約的な内容で、下に行くほど根拠・エビデンスを示す内容
なお、この記事は -ss
を入力パラメーター (-i
の前) として指定している前提で解説
-ss
の指定位置と FFmpeg の振る舞いについては次の記事を参照:
FFmpeg で keyframe でカットする方法 #ffmpeg - Qiita
要約
なぜカット編集するとカット位置のズレまたは再エンコードが発生するのか
FFmpeg の -ss
オプションで position
を指定してカット編集をする際に
position
から最初の keyframe
までの間をどのように処理するかを決定する必要があるため
図解
■: keyframe
□: non-keyframe
-: no frame
keyframe から始まらないこの区間をどうするか
|<---------------------------------->|
□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--
^ position
「やりたいこと」から「何をすればよいのか」の逆引き表
やりたいこと | 方法 | FFmpeg での 振る舞いの呼び方 |
---|---|---|
-ss で指定した position より前のkeyframe からになってもよいのでstream の再 encode を避けたい場合 |
stream の codec を copy に設定または -noaccurate_seek を設定 |
no accurate または inaccurate
|
再 encode が発生してもよいので-ss で指定した position 丁度からカットしたい場合 |
-accurate_seek を設定 |
accurate |
- 上記のいずれの方法も取らなかった場合は
accurate
の振る舞い- (FFmpeg 2.1 以降のデフォルトの振る舞いは
accurate
のため)
- (FFmpeg 2.1 以降のデフォルトの振る舞いは
- stream の
codec
をcopy
に設定しつつ-accurate_seek
を設定すると
no accurate
の振る舞いになる模様 (根拠は後述)
図解
no accurate
の場合
■: keyframe
□: non-keyframe
-: no frame
v seek point
|<-------
□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--
^ position
accurate
の場合
■: keyframe
□: non-keyframe
-: no frame
1. decode
|<----------------------------------------->|
v seek point
2.破棄 3. 再 encode
|<----->|<--------------------------------->|
□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--□--■--□--□--□--□--□--□--□--□--□--□--□--□--□--
^ position
用語の説明
position
と seek point
の意味
公式ドキュメントなどに明確な解説はないので、自分が FFmpeg を使った経験からの解釈で解説
次の通り:
用語 | 日本語 | 意味 |
---|---|---|
position |
位置 |
ffmpeg の -ss オプションなどで自由に指定できる timestamp |
seek point |
シークポイント |
動画ファイルの各フレームの離散的な timestamp |
position
と seek point
の違い
position
は自由に設定可能
一方で seek point
は入力ストリームの中でフレームが存在する時刻のみ
そのため、FFmpeg は position
で指定された直前の seek point
から実際の処理を実行
ファイルの形式によっては seek point
は keyframe
という情報も
Answer: command line - FFmpeg -ss option and keyframes - Super User
一部を和訳すると次の通り:
seek point
はkeyframe
を意味しますか?一般的には。
一部の形式 (MP4 など) には、各 stream のseek point
のリストが含まれています。
FFmpeg はその packet header を解析し、
keyframe
の index を組み立てようとします。
その他の形式では使用可能な metadata がないので、FFmpeg は seek に失敗します。
seek における accurate
(正確) とは「時間的に正確な位置に seek すること」
seek に関して accurate
, inaccurate
, noaccurate
という用語が使われるので、
そちらも解説
ソースは公式ドキュメントの -ss position (input/output)
の解説:
ffmpeg Documentation
用語 | 日本語 | 意味 |
seek point ~ position の間の処理 |
---|---|---|---|
accurate |
正確 |
時間的に正確な位置に seek すること | デコードされ破棄 |
inaccurate noaccurate
|
不正確 |
時間的に不正確な位置に seek すること (直前の keyframe に対してのみ seek) |
保持 |
オプション: -accurate_seek (input)
, -noaccurate_seek (input)
の解説
次の 2 つのドキュメントを要約して解説:
This option enables or disables accurate seeking in input files with the
-ss
option.
It is enabled by default, so seeking is accurate when transcoding.
Use-noaccurate_seek
to disable it, which may be useful
e.g. when copying some streams and transcoding the others.
Previous behavior
(seek only to nearest precedingkeyframe
, despite inaccuracy)
can be restored with-noaccurate_seek
.
-noaccurate_seek (input)
- FFmpeg 2.1 より前のデフォルト動作
- 不正確であっても、直前の
keyframe
に対してのみ seek する - 一部の stream を
copy
し、他の stream をトランスコードするときに便利
-accurate_seek (input)
-
-ss
オプションを使用した入力ファイルの正確なシークを有効化 - デフォルトで有効になっているため、トランスコード時のシークは正確
-
-noaccurate_seek
を使用して無効化可能
公式ドキュメントの記述
-ss position (input/output)
When used as an input option (before
-i
), seeks in this input file toposition
.
Note that in most formats it is not possible to seek exactly,
soffmpeg
will seek to the closestseek point
beforeposition
.
When transcoding and-accurate_seek
is enabled (the default),
this extra segment between theseek point
andposition
will be decoded and discarded.
When doing stream copy or when-noaccurate_seek
is used, it will be preserved.
日本語に翻訳すると概ね次の通り:
入力オプションとして (
-i
の前で) 使用する場合、この入力ファイル内で位置を seek します。
ほとんどの形式では正確に seek できないため、
ffmpeg
はposition
の直前のseek point
に seek します。
トランスコーディング時に-accurate_seek
が有効になっている場合 (デフォルト)、
seek point
とposition
の間のこの余分なセグメントはデコードされ、破棄されます。
stream のcopy
を実行する場合、または-noaccurate_seek
が使用されている場合は、
保持されます。
stream の codec
を copy
に設定しつつ -accurate_seek
を設定した場合、no accurate
の振る舞いになる根拠
実際に手元で何度か条件を変えて検証した結果より
何度条件を変えてカット編集しても、
FFprobe でカット編集後の動画ファイルの冒頭のフレームが次のようになることを確認:
-
keyframe
から開始 - 次の
keyframe
までの frame 数がその次のkeyframe
までの frame 数と一致