cBlog

Tips for you.

パラノイアのためのフレーム単位の動画カット編集

スポンサーリンク
※当ブログのAmazon、iTunes、サウンドハウス等のリンクはアフィリエイトを利用しています。

FFmpeg ロゴ

前提

  • 再エンコードしない
  • どのストリームも保持する(-map 0)

再エンコードなしでの動画の切り出しでは、P/Bフレームは前のフレームを必要とするので切り出しの開始はIフレーム、Bフレームは後のフレームを必要とするので切り出しの終了はI/Pフレームにする必要がある。

[謎] 2つにカットする場合、オープンGOPではどうやってもIフレームの重複を必要とするが、BDレコーダーではどうしているのだろう? 重複させると再連結する際に面倒。あるいは、末端のBフレームを再エンコードしている? 余力があれば調べる。

[追記 2020/11/01] 調べた。SonyのBDレコーダーではカット点に対し前の動画を「カット点を含むGOPの1つ後のGOPの最後のPフレームまで」、後の動画を「カット点を含むGOPの2つ前のGOPの最後のPフレームの次フレームから」出力していた。つまり、この記事の1文目の表記は絶対ではなかった。後の動画はBフレームから始まるが、当然表示はできない。だが、データ上は存在しているようで、他の動画と連結させると表示できるようになる。BDレコーダーによる再連結の際は、タイムスタンプを見ているのか重複することなくつながった。

オープンGOP:デコード画像の順でB→Iを含むもの→参考

Macの画面収録では、IBBPだが末端のBフレームをPフレームにしている。

[追記 2020/11/01] -map 0としたいところだが、字幕を含むとFFmpeg 4.2以降では-codec copyでmuxできない。ARIB Captionのデコードに対応したがエンコードには対応していないためである。libaribb24を有効化すればいい?

 

切り出し手順

1. Avidemuxでフレームタイプを確認しながら開始時間、終了時間を決める。

ffmpeg -ss 00:35.213 -to 00:45.322 -i in.m2ts -copyts -map 0 -c copy out.m2ts

-c copyとすると入力オプション(-iより前)の-toは無視されるが、-copytsをつけると可能になる。

“AAC bitstream not in ADTS format and extradata missing”が出る場合は-copytsの代わりに出力オプション(-iより後ろ)として-ss 0を(もう一度)つける。

[追記 2020/11/01] -copytsだけでなく-mpegts_copyts 1もつけないとptsがソースとずれる。これはmuxerにタイムスタンプをコピーするよう伝えるコードらしい。

2. 出力結果(out.m2ts)の端を確認する。必要に応じて、開始時間、終了時間を調整して再トライ。

両端のフレームを眼で確認。フレーム単位戻し/送りは、Avidemux、QuickTime Player:←/→キー、IINA:,/.キー。

両端のフレームタイプを確認(Avidemuxだと終端付近のBフレームが表示されない場合があった)。

ffprobe -read_intervals 01:00.000%03:00.000 -show_frames -select_streams 0 -show_entries frame=pkt_pts_time,pict_type:side_data= -of csv=p=0 out.m2ts | grep , | less

[補遺] タイムスタンプ/フレームタイプの確認は時間はかかるがこれでも可(画像、タイムスタンプ、フレームタイプを同時に確認できる)。

ffmpeg -i in.m2ts -vf "drawtext=fontfile=/System/Library/Fonts/HelveticaNeue.ttc:x=(w-tw)/2:y=(h-th)/2:fontsize=64:box=1:text='%{pts\:hms} %{pict_type}'" -q 5 -c:a copy pts.m2ts

[追記 2020/11/01] これも。

ffplay -v quiet -vf "drawtext=fontfile=/System/Library/Fonts/HelveticaNeue.ttc:fontsize=48:box=1:text='%{pts} %{pict_type}'"

 

結合

ffmpeg -f concat -i in.txt -map 0 -c copy out.m2ts

in.txtの内容は以下。

# This is comment
file 'path/to/00001.m2ts'
outpoint 73558.878144
file 'path/to/00002.m2ts'
inpoint 73558.878144

outpointinpointで同じ時刻を指定すると重複しない(inpointは指定時刻を含むがoutpointは含まない)。

あるいはワンライナー(同じ処理を表したものではない)。

ffmpeg -f concat -safe 0 -i <(printf "file '%s'\ninpoint 10:00.000" /absolute/path/to/in.m2ts) -map 0 -c copy out.m2ts

この場合、-safe 0と絶対パスであることが求められる。

 

質問

FFmpegでプログラム番号とPIDをキープ(設定)する方法