映像を重ねてワイプを作ったり、重ねた映像を動かしたりできる overlay フィルタの使い方。重ねる映像は動画と画像どちらもできる。重ねる映像の解像度が背景となる映像よりも小さくなければならない。

基本コマンド

input1 の中央に input2 の中央を配置。
ffmpeg -i input1 -i input2 -filter_complex overlay="x=(W-w)/2:y=(H-h)/2" output

右下隅から左上10ピクセルに配置。
"overlay=x=main_w-overlay_w-10:y=main_h-overlay_h-10"

右上から左上に向かって1フレーム1ピクセル移動する。
"overlay=x=W-n:y=0"

1枚の画像をオーバーレイするにはループ入力する。
ffmpeg -i video.mp4 -loop 1 -i img.jpg -filter_complex overlay="x=(W-w)/2:y=(H-h)/2" output

動画をループ入力する。
ffmpeg -stream_loop -1 -i video.mp4 -loop 1 -i img.jpg -filter_complex overlay="x=(W-w)/2:y=(H-h)/2" -fflags +genpts output

ffmpeg で無限入力が可能に
ループ回数を指定できる loop, aloop

1枚画像どうしを入力して1枚画像にする場合にはループ入力しなくてよい。
ffmpeg -i img1.jpg -i img2.jpg -filter_complex overlay="x=(W-w)/2:y=(H-h)/2" output.jpg

アニメGIF, APNG は ignore_loop 0 を付けると無限ループする。アニメWebp は現在のところデコードできない。
ffmpeg -i video.mp4 -ignore_loop 0 -i img.gif -filter_complex overlay="x=(W-w)/2:y=(H-h)/2" output

透過部分だけに色を付ける
ffmpeg で動画にロゴ画像を追加し透過させる

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

オプション

  • x[string]
    オーバーレイする映像の左上の横座標。評価式が使える
  • y[string]
    オーバーレイする映像の左上の縦座標。評価式が使える
  • eof_action[int]
    2入力した映像が終了したときの1入力した映像の挙動指定。framesync を参照
  • eval[int]
    x, y で指定した値どのように更新するか
    • 0, init:最初に決めたら更新しない
    • 1, frame:フレーム毎に更新。既定値
  • shortest[boolean]
    時間の短いファイルが最後まで処理したら終了する
    既定値:0(終了しない)
  • format[int]
    出力フォーマットの指定
    • yuv420:既定値
    • yuv422
    • yuv444
    • rgb
    • gbrp
    • auto
  • repeatlast[boolean]
    時間の短いファイルが最後まで処理し、時間の長いファイルが最後まで処理し終わるまで、時間の短いファイルの最終フレームを繰り返す
    既定値:1(終了する)
  • alpha[int]
    合成モードの指定。詳しくは後述
    • 0, straight:unpremultiplied, non-premultiplied とも言う。既定値
    • 1, premultiplied

評価式

ffmpeg で使える計算書式 を使って複雑な計算ができる。

  • main_w, W:1入力目の横の解像度
  • main_h, H:1入力目の縦の解像度
  • overlay_w, w:1入力目の横の解像度
  • overlay_h, h:2入力目の縦の解像度
  • x:x で指定した値
  • y:y で指定した値
  • hsu:横方向のクロマサブサンプル値。yuv422p なら 2
  • vsub:縦方向のクロマサブサンプル値。yuv422p なら 1
  • n:映像のフレーム数。0開始
  • pos:映像のバイトサイズの位置。不明なら NAN
  • t:映像のタイムスタンプ秒。不明なら NAN

応用例

タイムスタンプのエラーが出るときには2入力ともに setpts=PTS-STARTPTS フィルタを当てて開始時間を0秒からにする。
ffmpeg -i input1 -i input2 -filter_complex [0:v]setpts=PTS-STARTPTS[0v];[1:v]setpts=PTS-STARTPTS[1v];[0v][1v]overlay="x=(W-w)/2:y=(H-h)/2" output

x y
左上隅 0 0
右上隅 W-w 0
左下隅 0 H-h
右下隅 W-w H-h

ループ

表示方法は2通りあり、端に見切れ初めてすべて見切れたときに再び表示される場合と、見切れたら同時に再び表示する場合がある。後者は同時に2つの映像がオーバーレイされているので2度 overlay フィルタを当てる。

右上から左上にループ。
ffmpeg -i input1 -i input2 -filter_complex overlay=x=W-mod(n\,W+w):y=0" output

1表示ループ x y
左から右 mod(n\,W+w)-w
右から左 W-mod(n\,W+w)
下から上 H-mod(n\,H+h)
上から下 mod(n\,H+h)-h

右上から見切れずに左上にループ。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=W-mod(n\,2*W):y=0[o];[o][1:v]overlay=x=W-mod('if(between(n,0,W),0,n-W)'\,2*W):y=0" output

2表示ループ x x
左から右 -w+mod(n\,2*w) -w+mod(‘if(between(n,0,W),0,n-W)’\,2*W)
右から左 W-mod(n\,2*W) W-mod(‘if(between(n,0,W),0,n-W)’\,2*W)
2表示ループ y y
下から上 H-mod(n\,2*H) H-mod(‘if(between(n,0,H),0,n-H)’\,2*H)
上から下 -h+mod(n\,2*H) -h+mod(‘if(between(n,0,H),0,n-H)’\,2*H)

対角線

左上から右下。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=-w+((W+w)/(H+h))*n:y=-h+n" output

左下から右上。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=-w+((W+w)/(H+h))*n:y=H-n" output

対角線 x y
左上から右下 -w+((W+w)/(H+h))*n -h+n
右上から左下 W-((W+w)/(H+h))*n -h+n
左下から右上 -w+((W+w)/(H+h))*n H-n
右下から左上 W-((W+w)/(H+h))*n H-n

時計回り、反時計回り

適宜+-60の部分とsin(), cos() を入れ換えれば開始位置と回転方法を変えられる。回転速度は *n を変更する。

中央右60ピクセルから時計回りに回る。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=(W-w)/2+60*cos((PI*n)/180):y=(H-h)/2+60*sin((PI*n)/180)" output

中央右60ピクセルから反時計回りに回る。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=(W-w)/2+60*cos((PI*n)/180):y=(H-h)/2-60*sin((PI*n)/180)" output

中央上60ピクセルから時計回りに回る。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=(W-w)/2+60*sin((PI*n)/180):y=(H-h)/2-60*cos((PI*n)/180)" output

中央上60ピクセルから反時計回りに回る。
ffmpeg -i input1 -i input2 -filter_complex "overlay=x=(W-w)/2-60*sin((PI*n)/180):y=(H-h)/2-60*cos((PI*n)/180)" output

x y
中央 (W-w)/2 (H-h)/2
時計回り、右 (W-w)/2+60*cos((PI*n)/180) (H-h)/2+60*sin((PI*n)/180)
反時計回り、右 (W-w)/2+60*cos((PI*n)/180) (H-h)/2-60*sin((PI*n)/180)
反時計回り、左 (W-w)/2-60*cos((PI*n)/180) (H-h)/2+60*sin((PI*n)/180)
時計回り、左 (W-w)/2-60*cos((PI*n)/180) (H-h)/2-60*sin((PI*n)/180)
時計回り、上 (W-w)/2+60*sin((PI*n)/180) (H-h)/2-60*cos((PI*n)/180)
反時計回り、上 (W-w)/2-60*sin((PI*n)/180) (H-h)/2-60*cos((PI*n)/180)
時計回り、下 (W-w)/2-60*sin((PI*n)/180) (H-h)/2+60*cos((PI*n)/180)
反時計回り、下 (W-w)/2+60*sin((PI*n)/180) (H-h)/2+60*cos((PI*n)/180)

alpha モード

オーバーレイする動画に予め透過具合に応じて色を変更するのが premultiplied

詳しい話は外部記事で。
コンポジターに必要なアルファチャンネルの知識(前編) – コンポジゴク
コンポジターに必要なアルファチャンネルの知識(後編) – コンポジゴク

ffmpeg -f lavfi -i color=red,format=rgba,geq='p(X,Y):p(X,Y):p(X,Y):clip(255-sqrt(pow(X,2)+pow(Y,2)),0,255)',lutrgb=255:val:val:val -vframes 1 red.png
ffmpeg -f lavfi -i color=gray,format=rgba -vframes 1 gray.png
ffmpeg -i gray.png -i red.png -filter_complex overlay=alpha=0:format=rgb overlay-alpha0.png
ffmpeg -i gray.png -i red.png -filter_complex overlay=alpha=1:format=rgb overlay-alpha1.png
赤背景に左上から円周上に透過

グレー一色

overlay=alpha=0、Rが透過具合によって減少

overlay=alpha=1、Rだけに少しづつGBが加算

overlay_opencl

opencl を使って overlay_opencl フィルタを使う。

opencl が使えれば以下のコマンドを実行すると対応 CPU、または GPU が表示される。
ffmpeg -hide_banner -v verbose -init_hw_device opencl

出力コマンド例。

ポイントは opencl を使うデバイスを上の例では 0.0 から 1.1 から指定する。能力によって処理速度が大きく異なる。オプション指定は通常と同じ。

コマンド例。ポイントは2入力とも hwupload フィルタを使う。
ffmpeg -init_hw_device opencl=ocl:1.0 -filter_hw_device ocl -i video.mp4 -loop 1 -i img.png -filter_complex "[0:v]hwupload[0v];[1:v]format=yuva420p,hwupload[1v];[0v][1v]overlay_opencl" output

通常のフィルタに切り替えるには hwdownload,format=yuv420p フィルタを挟む。
ffmpeg -init_hw_device opencl=ocl:1.0 -filter_hw_device ocl -i video.mp4 -loop 1 -i img.png -filter_complex "[0:v]hwupload[0v];[1:v]format=yuva420p,hwupload[1v];[0v][1v]overlay_opencl,hwdownload,format=yuv420p,lutyuv=val:128:128 output

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

コメントを残す

メールアドレスが公開されることはありません。

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