2022年1月16日日曜日

FFMPEGに関する備忘録

 ちょっとワケがあって、FFmpegで映像に静止画像を重ね合わせる処理をさせる必要に迫られました

 本来なら、対話型の動画編集ソフトを使って編集、エンコードするのが普通で、最近はDavinci Resolve(公式サイトはこちら)なんていう良いソフトもあるので、出来上がりを見ながら作り込んでいくなら、対話式の動画編集ソフトの方がやりやすいと思います。

しかし、決まり切った処理を何回もやらなければならない、という状況を想定すると、対話型のソフトはちょっと使いたくないです。何かいい手は無いかと考えたとき、選択肢に上がるのがFFmpegだろうと思います。

 FFmpegというのは、昔からある有名なオーディオ/映像ストリームに色んな処理を加えることのできる、コマンドラインで動くフリーソフトです。フリーの映像/画像処理ソフトの中には、このソフトを処理エンジンとして使っているものもあるように思います。こちらが公式サイトです

この、コマンドラインで動く、というのが重要で、巨大な映像ファイル/プロジェクトを、その都度動画編集ソフトで開く、ということをしなくても良いのです。unixでテキストファイルをsedで編集するのと考え方が似ていると思います。

ただ、コマンドラインの書き方がとても難しくて、なかなか覚えられないのが難点です。あちこち調べ回って、トライ・アンド・エラーでなんとか動かすことに成功したので、忘れないように書き留めておきます。

まず、素材。

これは透過PNGで作った画像で、1280X720ピクセルの大きさがあります。

flag.png
次の画像はこれです。やはり透過PNGで作った画像です。400X389ピクセルの大きさがあります。
これを、下地となる動画に貼り付けるのです。

logo.png

下地となる動画は、3840X2160ピクセルのH.264、約3分33秒の動画となっています。GoPro Hero9で撮影したものをVNで編集して作成しています。一昔前だとパソコンで再生するのは無理、というほど大きな動画ですね。



これが、その下地となる動画です。main.mp4と名付けておきます。

今回は、このmain.mp4を1280X720のHDサイズに縮小したのち、上に出した静止画2つを重ね合わせますが、最初の静止画は縮小後の動画と同サイズなので、大きさ、場所ともそのまま、ただし不透明度を30パーセントに設定して、重ね合わせます。

2枚目の静止画は、動画の右上の隅に配置するように重ね合わせます。これをDavinci Resolveで処理したものが、以下です。


ちなみにこの処理を、Mac Book Pro 16インチモデルのDavinci Resolveは1分17秒で完了しました。これはIntel UHD Graphics 630とAMD Radeon Pro 5500Mという、GPUを2つ積んだマシンなのですが、アクティビティモニターを見ると、両方とも動いています。

さて、上記処理(に近いもの)をFFmpegで行うためのコマンドラインの書き方ですが、

ffmpeg -i main.mp4 -loop 1 -i logo.png -i flag.png \
    -filter_complex \
    "[0:v]scale=1280:-1[v1]; \
    [1:v]scale=200:-1[a]; \
    [2:v]lut=a='val*0.4'[b]; \
    [v1][b]overlay=0:0[v0]; \
    [v0][a]overlay=(W-w)-10:10:shortest=1" \
    -c:a copy -c:v h264_videotoolbox -b:v 20000k output.mp4

バックスラッシュはエスケープ文字で、その次にある改行文字をエスケープするためのもの。なので、最初から最後まで本来は1行です。

 以下、コマンドラインの説明です。

-i

入力ファイルの指定です。後ろに続くものを入力ファイルとして扱いますこのファイルの順番は、あとでちゃんと意味を持つので、気にとめて置いてください。ここでは、main.mp4、logo.png、flag.pngを入力ファイルとして指定しています。

-loop

後に続く入力ファイルをループするものとして指定するためのオプションです。続く数字で意味が変わってきます。-loop 1で、静止画を繰り返すという意味になるようです。

-filter_complex

複数のフィルターを組み合わせて使うときに、このfilter_complexというキーワードを使います。このキーワードの後ろに""で囲んだ複数のフィルターを記載します。

[0:v]scale=1280:-1[v1];

-i オプションで指定した一番最初の入力ファイルのビデオ部に対して、横幅1280ピクセルで同一アスペクト比のスケーリングをして、そのストリームデータにv1という名前を付けます。[0:v]の:vがビデオ部を指定するキーワードになっています。scale=横の長さ:縦の長さという書式ですが、片方だけを指定して、同じアスペクト比にしたい場合は、-1を指定します。

[1:v]scale=200:-1[a]; 

-iオプションで指定した2番目の入力ファイルのビデオ部に対して、横幅200ピクセルで同一アスペクト比のスケーリングを行い、そのストリームデータにaという名前を付けます。

 [2:v]lut=a='val*0.4'[b];

3番目の入力データのビデオ部に対して、画素値を0.4倍にする処理をします。これによって、不透明度を40パーセントに落としています。

[v1][b]overlay=0:0[v0];
ストリーミングデータのv1にbを重ね合わせて、重ね合わせたストリーミングデータにv0という名前を付けます。overlay=0:0は重ね合わせ画像の左上の座標をx座標、y座標とも0に指定します。

[v0][a]overlay=(W-w)-10:10:shortest=1" 

ストリーミングデータのv0にaを重ね合わせます。重ね合わせ期間を、最も短いストリーミングデータ(この場合はmain.mp4の長さ)にします。

-c:a copy

-cはコーデックの指定をするオプションで、-c:aと記述すると、オーディオのコーデックを指定する記述となります。-c:a copyは、オーディオのデータは、元のデータをそのままコピーして使う、という意味になります。

-c:v h264_videotoolbox

ビデオ部のコーデックに、h264_videotoolboxを使うことを指示します。h264_videotoolboxは、MacOS用に用意された映像処理用のライブラリで、その中にあるH.264用コーデックを使うために指定するものです。ハードウエアエンコードを含めた、最適なコーデックを選択してくれます。ちなみに、H.265を扱いたい場合は、hevc_videotoolboxを使います。

-b:v 20000k

-bは最大ビットレートを指定するオプションです。-b:v 20000kは、ビデオ部の最大ビットレートを2Mbpsにする、という指示です。

output.mp4

出力ファイルをoutput.mp4にします。なお、-f matroska - | ffplay -i -と記述すると、出力をファイルではなく、標準出力経由でffplayに渡し、ffplayでプレビューする、ということができます。

-fは、出力を強制的にフォーマット変換するためのオプションで、上記記述では、マトリョーシカフォーマットに変換して、標準出力(-)に出力する、という意味です。 

上記コマンドラインを指定して、FFmpegで処理した動画が以下です。