Avisynth で言うところのSubtractを ffmpeg のblendを使って差分を表示して比較動画を作る方法。

YUV RGB を比較計算する blend

使うフィルタはblendで設定できる内容はたくさんあるが使うのは difference モードで2つの映像の差異を表示する。そのほかにも映像の YUVA/RGBA の値を四則演算できるが、それぞれの詳しい内容は理解していない。詳しい処理はソースコードを参照。

フレームレートを 30000/1001 から 24000/1001 に間引く場合はdecimateするときれいに間引ける。インターレース解除はyadif、フレーム数の指定でのカットはtrimを使う。yadif, trim, decimate, setpts の順番にフィルタをかける。

コマンドサンプル

  • 比較動画として上に二つ並べて左下に差分(Y は 0 差分、UV は1入力)の動画を表示するコマンド例
    ffplay -f lavfi "movie=left.mp4,setpts=PTS-STARTPTS,split[a1][a2];movie=right.mp4,setpts=PTS-STARTPTS,split[b1][b2];[a1][b1]blend=c0_mode=difference,pad=2*iw:ih:0:0[blend];[a2][b2]hstack[tmp];[tmp][blend]vstack"
  • 比較動画として上に二つ並べて左下に差分(Y は 0 差分、UV は 128 からの差分)の動画を表示するコマンド例(上よりもこちらの方が正確)
    ffplay -f lavfi "movie=left.mp4,setpts=PTS-STARTPTS,split[a0][a1];movie=right.mp4,setpts=PTS-STARTPTS,split[b0][b1];[a0][b0]blend=all_mode=grainextract,lutyuv=val-128,pad=2*iw:ih:0:0[down];[a1][b1]hstack[up];[up][down]vstack"
  • フレームレートを間引いて比較する例
    ffplay -f lavfi "movie=7.mp4,trim=start_frame=1:end_frame=3000,decimate,setpts=PTS-STARTPTS,split[a0][a1];movie=11.mp4,trim=start_frame=1381:end_frame=4077,decimate,setpts=N/(24000/1001)/TB,setpts=PTS-STARTPTS,split[b0][b1];[a0][b0]blend=all_mode=grainextract,lutyuv=val-128,pad=2*iw:ih:0:0[down];[a1][b1]hstack[up];[up][down]vstack"
  • 透過を指定することで右上依りの映像にすることもできる
    ffplay -f lavfi "movie=left.mp4,setpts=PTS-STARTPTS,split[a1][a2];movie=right.mp4,setpts=N/(24000/1001)/TB,setpts=PTS-STARTPTS,split[b1][b2];[a1][b1]blend=c0_mode=difference:all_opacity=.5,pad=2*iw:ih:0:0[blend];[a2][b2]hstack[tmp];[tmp][blend]vstack"
  • 動画出力する場合
    ffmpeg -i left.mp4 -i right.mp4 -filter_complex "[0:0]setpts=PTS-STARTPTS,split[a1][a2];[1:0]setpts=PTS-STARTPTS,split[b1][b2];[a1][b1]blend=c0_mode=difference,pad=2*iw:ih:0:0[blend];[a2][b2]hstack[tmp];[tmp][blend]vstack" -acodec copy -vcodec libx264 output.mkv

    ffmpeg の blend フィルタより difference モードから差分を表示。画像は「結城友奈は勇者である」の11話と7話の Yチャンネルの OP差分。

効果を調べるのに YUV の変化を調べると一層わかりやすい。
YUV、彩度、色相 を見える化する signalstats

averageでフレーム毎のずれを見ることもできる
フレームで時間を指定する場合はtrimsetptsを併用する。リサイズは最終出力時よりも個別にリサイズした方が早い。
ffmpeg -i left.mp4 -i right.mp4 -filter_complex "[0:0]scale=426:-1,trim=start_frame=2908:end_frame=5605,setpts=PTS-STARTPTS,split[L][L1];[0:1]atrim=start_sample=4656000:end_sample=8976000,asetpts=PTS-STARTPTS[a1];[1:0]scale=426:-1,trim=start_frame=2098:end_frame=4795,setpts=PTS-STARTPTS,split[R][R1];[L][R]hstack[up];[L1][R1]blend=all_mode=average,pad=852:240:213:0[down];[up][down]vstack[v]" -map [vout] -map [a1] out.mp4

ffplay でプレビューするコマンド
ffplay -f lavfi "movie=left.mp4,scale=426:-1,trim=start_frame=2908:end_frame=5605,setpts=PTS-STARTPTS,split[a1][a2];movie=right.mp4,scale=426:-1,trim=start_frame=2908:end_frame=5605,setpts=PTS-STARTPTS,split[b1][b2];[a1][b1]blend=all_mode=average,pad=852:240:213:0[down];[a2][b2]hstack[up];[up][down]vstack"

pad, overlay の使い方は以下を参照

公式ドキュメント:FFmpeg Filters Documentation : blend, tblend

関連記事

コメントを残す

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

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