一定のフレーム間隔で重複フレームを間引くdecimateフィルタと、前フレームとあまり変化のないフレームを間引くmpdecimateフィルタの使い方。

Windows の ffmpeg で生放送する方法で書いていた内容をこちらに引っ越し内容を修正した。

一定周期のフレームを間引くフィルタにshuffleframesフィルタがある。
指定フレーム毎に順番を入れ換える shuffleframes

Remove sequentially duplicate frames when using FFmpeg – Stack Overflow

decimate

間引くフレームは2番目の重複フレームで、PTSを修正し元のフレームレートよりも少なく出力する。

基本コマンド

日本の映像データは一般的に5フレーム毎に1フレーム間引けば重複フレームがなくなるので既定値のままでよい。
ffmpeg -i input -vf decimate=cycle=5:dupthresh=1.1:scthresh=15:blockx=32:blocky=32:ppsrc=0:chroma=1 -c:a copy output
ffplay -i input -vf decimate

ppsrc=1を使いlutyuvフィルタで少し明るくする。
ffmpeg -i input -vf split[1],lutyuv=y=gammaval(1/1.1)[0];[0][1]decimate=ppsrc=1 -c:a copy output
ffplay -i input -vf split[1],lutyuv=y=gammaval(1/1.1)[0];[0][1]decimate=ppsrc=1

公式ドキュメント:FFmpeg Filters Documentation : decimate

オプション

  • cycle[int]
    間引く1フレームを決めるフレーム周期の指定
    既定値:5
    範囲:2から25まで
  • dupthresh[double]
    重複フレームを検出するしきい値の指定
    既定値:1.1
    範囲:0から100まで
  • scthresh[double]
    シーンチェンジの閾値の設定
    既定値:15
    範囲:0から100まで
  • blockx, blocky[int]
    計算に使うx軸とy軸のブロックサイズを指定する。値が大きいほどノイズの抑制になるが小さな動きの検出は悪くなる。2の累乗でなければならない
    既定値:32
    範囲:4から512まで
  • ppsrc[boolean]
    あらかじめデノイズなどを行った1入力目の映像から重複フレームを調べ、2入力目の映像に1入力目の重複を調べた結果を反映させる。実際のフレーム間引きには1入力目のフィルタの影響はない
    既定値:0(無効)
  • chroma[boolean]
    重複フレームを検出する計算に彩度を考慮する
    既定値:1(有効)
  • mixed[boolean]
    映像に間引くのと間引かないのが両方含まれるときの設定
    既定値:0(無効)

mixedの挙動について

アニメだと初期のノイタミナのOPクレジットや一部のトランジション、販促などのスクロールテロップ、OPEDのクレジットなどが片フィールドやインターレースになっていないときに、それ以外の本編のフレームレートと異なるときに使う。

24と30の最小公倍数の120にフレームレートを合わせて、24の部分は5フレームごとに動き、30の部分は4フレームごとに動く。
ffmpeg -i input.ts -map 0:v -c:v libx264 -vf fps=fps=30000/1001,fieldmatch,decimate=mixed=1,fps=fps=120000/1001 -preset slow -crf 18 output.mp4

mpdecimate

重複フレームを間引き、PTSは修正せずに可変フレームレートで出力する。-vsyncか、setpts、fpsフィルタを併用しないと間引いたフレームに再び元のフレームレートに合わせてフレームを複製するので意図した挙動にならない。似た映像を間引きdecimateフィルタのように一定間隔の重複フレームを間引くには扱いにくい。

-vsyncの内容はffmpeg でのフレームレート設定の違い | 可変フレームレートの項目で説明している。-vsyncでエラーがでるときは-fps_modeにかえる。

基本コマンド

固定間隔ではない重複フレームを間引いたのをそのまま再生するには重複フレームが元のフレームレートに合わせて複製されるので有用ではない。
ffmpeg -i input -vf mpdecimate=max=0:hi=768:lo=320:frac=0.33,setpts=N/FRAME_RATE/TB -vsync vfr -c:a copy output.mp4

メタデータ出力に対応していないのでnull出力したログで調べる必要がある。
ffmpeg -loglevel level+debug -i input -vf mpdecimate -an -sn -dn -f null - 2>&1 | grep -e Parsed_mpdecimate | grep -e drop_count

公式ドキュメント:FFmpeg Filters Documentation : mpdecimate

オプション

  • max[int]
    連続して間引くフレーム間隔の指定。正の値ならフレーム間隔の最大値。負の値なら間引く1フレームを決めるフレーム間隔の最小値。0は最初のフレームを除きすべての重複フレームを間引く。具体例は後述
    既定値:0
    範囲:INT_MINからINT_MAXまで
  • hi[int]
    間引くしきい値の指定。8×8ピクセルを1単位としてこの値の上限を間引く候補とする
    既定値:768(8x8x12)
    範囲:INT_MINからINT_MAXまで
  • lo[int]
    間引くしきい値の指定。8×8ピクセルを1単位としてこの値の下限を間引く候補とする
    既定値:320(8x8x5)
    範囲:INT_MINからINT_MAXまで
  • frac[float]
    探索する1フレーム画像の割合
    既定値:0.33
    範囲:0から1まで

maxの挙動について

黒単色24フレームレートで10秒の動画をテストに使い、それぞれmaxに値を代入する。代入する値をnとすると以下のような出力フレームになる。

0を指定すると1フレームだけ出力する。
ffmpeg -f lavfi -i color=r=24:d=10 -vf mpdecimate=max=0,setpts=N/FRAME_RATE/TB -vsync vfr -c:v ffv1 color.mkv

正の値を指定する。割合は1/(n+1)でnは1以上とする。
ffmpeg -f lavfi -i color=r=24:d=10 -vf mpdecimate=max=1,setpts=N/FRAME_RATE/TB -vsync vfr -c:v ffv1 color.mkv

nの値 出力フレーム数 割合
1 120 1/2
2 80 1/3
3 60 1/4
5 40 1/6
10 22 1/11

負の値を指定する。割合は-(n+1)/nでnは-2以下とする。
ffmpeg -f lavfi -i color=r=24:d=10 -vf mpdecimate=max=1,setpts=N/FRAME_RATE/TB -vsync vfr -c:v ffv1 color.mkv

nの値 出力フレーム数 割合
-1 120 1/2
-2 120 1/2
-3 160 2/3
-5 192 4/5
-10 216 9/10

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)