0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FFmpeg でカット編集する際、カット位置のズレまたは再エンコードどちらかが必ず発生

Last updated at Posted at 2024-09-01
  • 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 の codeccopy に設定
または
-noaccurate_seek を設定
no accurate
または
inaccurate
再 encode が発生してもよいので
-ss で指定した position 丁度から
カットしたい場合
-accurate_seek を設定 accurate
  • 上記のいずれの方法も取らなかった場合は accurate の振る舞い
    • (FFmpeg 2.1 以降のデフォルトの振る舞いは accurate のため)
  • stream の codeccopy に設定しつつ -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

用語の説明

positionseek point の意味

公式ドキュメントなどに明確な解説はないので、自分が FFmpeg を使った経験からの解釈で解説

次の通り:

用語 日本語 意味
position 位置 ffmpeg の -ss オプションなどで自由に指定できる timestamp
seek point シークポイント 動画ファイルの各フレームの離散的な timestamp

positionseek point の違い

position は自由に設定可能
一方で seek point は入力ストリームの中でフレームが存在する時刻のみ
そのため、FFmpeg は position で指定された直前の seek point から実際の処理を実行

ファイルの形式によっては seek pointkeyframe という情報も

Answer: command line - FFmpeg -ss option and keyframes - Super User

一部を和訳すると次の通り:

seek pointkeyframe を意味しますか?

一般的には。
一部の形式 (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 つのドキュメントを要約して解説:

ffmpeg Documentation

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.

Seeking – FFmpeg

Previous behavior
(seek only to nearest preceding keyframe, 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 を使用して無効化可能

公式ドキュメントの記述

ffmpeg Documentation

-ss position (input/output)

When used as an input option (before -i), seeks in this input file to position.
Note that in most formats it is not possible to seek exactly,
so ffmpeg will seek to the closest seek point before position.
When transcoding and -accurate_seek is enabled (the default),
this extra segment between the seek point and position will be decoded and discarded.
When doing stream copy or when -noaccurate_seek is used, it will be preserved.

日本語に翻訳すると概ね次の通り:

入力オプションとして (-i の前で) 使用する場合、この入力ファイル内で位置を seek します。
ほとんどの形式では正確に seek できないため、
ffmpegposition の直前の seek point に seek します。
トランスコーディング時に -accurate_seek が有効になっている場合 (デフォルト)、
seek pointposition の間のこの余分なセグメントはデコードされ、破棄されます。
stream の copy を実行する場合、または -noaccurate_seek が使用されている場合は、
保持されます。

stream の codeccopy に設定しつつ -accurate_seek を設定した場合、no accurate の振る舞いになる根拠

実際に手元で何度か条件を変えて検証した結果より

何度条件を変えてカット編集しても、
FFprobe でカット編集後の動画ファイルの冒頭のフレームが次のようになることを確認:

  • keyframe から開始
  • 次の keyframe までの frame 数がその次の keyframe までの frame 数と一致
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?