映像を重ねてワイプを作ったり、重ねた映像を動かしたりできる 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) |
時計回り、反時計回り
適宜+-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) |
対角線
左上から右下
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 |
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