FFmpegで傾けた動画合成
2023年2月21日

FFmpegでrotateした動画をoverlayする話。

投稿者: 片原
こんにちは~。
約一ヶ月ぶりの投稿の片原です。
その間に、
何をやっていたか。。。


猛虎キャンプリポートを・・・(^o^☆\(-_-;;


スイマセン。
冗談は置いといて、超久々に技術的(FFmpegでrotateした動画をoverlayする話)な投稿を。(汗)
ヨルナビ・リニューアル後にインスタのようなストーリーズを実装予定なのですが、
今日はそこに使う動画合成についての話です。
紆余曲折ありました。

ffmpeg.wasmを駆使してなんとか端末側で合成したものを
アップロードすることを試みましたが、
端末によって差がありすぎて、
処理に何分もかかってしまうのでは使い物にならない。
ある程度、動画のカットまでを端末側でして、
合成をサーバー側のFFmpegでしようという事になりました。

FFmpegのrotateとoverlayの挙動

ヨルナビでは、アイキャッチのように、
動画を斜めに配置するという機能を付けてしまいました。
FFmpegのrotateでそれを実現できそうですが、
ちょっとクセがありあそうです。
下の画像のように、見切れてしまうのです。
FFmpegのrotateで見切れた動画合成

傾ける前の動画の大きさのまま見切れてしまってるんです。
見切れた部分を分かりやすく黒バックで合成すると、こんな感じです。
ffmpegのrotateで傾ける前の動画の大きさ



ググると、あまり数はないのですが、
見切れてしまうのを見きれないように余分に動画のサイズを大きくする等
記事がありました。
めっちゃ参考になりました。

が!

あまり細かな事を書いている記事がなかったので、
実用的ではありません。
雑に幅を見切れないように大きくした動画をoverlayで合成すると当然こうなります。(笑)
rotateで見切れないように拡大してズレた動画

ポイントを書くと、
rotateした際にrotw()という関数で傾けた際の幅を出せるのですが、
このrotwはoverlay時には使えないので、そこからの差異を減算して
x,yを算出できないんですね。
そこでどうしたか?


予め三角関数を用いてFFmpegに渡す

中学・高校生の皆さん。
確率統計とかは使うことあるかもだけど、
三角関数とか微積分、一体何に使うの?意味あんの?
そう思ってる現役学生の人、結構多いんじゃないでしょうか。

結論からいいますと、
使います!

公式見つける人ってホンマ天才やなと、
いつも思います。
現役時代は数学大好きだった片原も、めっぽう律儀な性格なので、
全て先生にお返ししてきました。
そこからはや数十年。

三角関数?
sin?cos?tan?

忘れてもーとるわw

え?そこから?

話を戻すと、
こんなイメージで計算したデータをffmpegに渡しました。
こんなイメージで計算したデータをffmpegに渡しました。

ライムグリーンの点線が元の動画の大きさですが、
ライムグリーンの実線が変換後の動画の大きさです。
って事は、
この、赤のaと、青のbさえ分かれば、
rotate後のサイズが分かるって訳です。

 

FFmpegにパラメータを渡す前の計算式

 
動画のサイズは分かっていますから、
その対角線はsqrt($w*$w+$h*$h)で算出できますね。

ここから先生に返上した三角関数の出番ですw

傾けた角度は編集時に何度傾けたかを測ってますので、
対角線と長辺の内角さえ分かれば、赤のθが分かります。
内角を求める計算式はこんな感じ。
 
180/pi()*atan($w/$h) 
 
abs(傾斜角度)+内角 
 
これで赤のθが出ました。
  
対角線長*sin(θ*pi()/180) 
 
これでrotate後の幅が出ました。
いよいよ、rotate後の幅と動画の幅の差を出します。
 
$x-(rotate後の幅-動画幅)/2 
 
これが新しいx座標ですね。
同じような扱いで、
高さ(青のb)も算出します。

数学大好き(だった)人間はこれを調べる間、
めっちゃワクワクするんですよね~。


FFmpegに実際にパラメータを渡す

上記の計算式を経て、作られたFFmpegへのコマンドがこれ。
 
ffmpeg -y -i input_bg.mp4 -i input.mp4 -i input-c.png -filter_complex ‘[1]scale=639.36:1136.64[v0];[v0]rotate=-22*PI/180:ow=1018.5971075961:oh=1293.3827280212:c=none[v1];[0:v][v1]overlay=17.289609467268:151.1286359894[v2];[v2][2:v]overlay’ -codec:a copy output.mp4 
 
これをexec()またはshell_exec()に渡して実行すると、
下の動画ができあがり~♪

filter_complexのパラメータ内容と実際の動きを理解すると面白いので、
ここでは深く掘らず、そこも調べる余地を残しておきますね~。


そんな訳で、(どんな訳?)
もっと詳しく聞きたい!って好奇心旺盛な貴方や、
こんなの作ってほしいけどお幾らなの?というイケてる貴方!
グランテストにお問い合わせくださいっ♪