ffmpeg で簡単な動画を作る

Linux で動画を作るためにいいソフトないか? いくつか試した中で結局 KDEnlive を使っていたものの、静止画動画を作る程度でもファイルサイズが大きくなってしまい使い勝手が良くない。最初にビデオサイズの規格とか決めなきゃいけないとかも、なんかよくわからん。

ところで AI ツールを使っていると、ありとあらゆるところで ffmpeg が出てくるんだよね。StableDiffusion の拡張で動画生成するときも、SadTalker でリップシンク動画作るときも、RVC や GPT-SoVITS で音声に関わるときもそうだ。それどころか、動画編集の Web サービスなんかも、この ffmpeg をラップしているだけらしい。

上記の KDEnlive でも ffmpeg を使っている。ffmpeg はコマンドラインから扱える単一のツールであり、これを使いこなせば大抵のことはできるのではなかろうか? と思い立ち、ChatGPTに聞きつつ、いろいろ勉強、実践してみることにした。

ステップ1:静止画動画を作る

静止画動画、あるいは音声動画ってのは一枚絵と音声を合わせたもの。動画の意味あるのか? 動画は投稿できるが音声は投稿できないケースは多く、俺は頻繁に使う。動かないならば、そのぶんファイルサイズを節約できるし、動かないことにもメリットはある。けどあまり使っている人らいねえんだよな。波形やら字幕やら口パクやら、何かしら視覚的要素も欲しいのが人情かもしれない。

さて基本中の基本として、静止画動画を作ってみよう。コマンドは

ffmpeg -loop 1 -r 25 -i ./input_img.jpeg -i ./input_audio.opus -shortest -c:v h264 -pix_fmt yuv420p ./output.mp4
-loop 1

入力をループさせる。今回1枚絵なのでループさせないと画像が一瞬で終わってしまう。

-r 25(省略可)

フレームレートの設定。容量を軽くするためには少ないほうが良さそうだが、なぜかむしろ重くなる。50 などにしても重くなる。標準の25のままでいいかもしれないが静止画動画と、通常の動画では事情が変わるだろう。必要に応じて調整できるようにしておく。

-i ./input_img.jpeg -i ./input_audio.opus


input_img.jpeg と input_audio.opus をそれぞれ入力ソースとして指定。./ はファイル名であることを強調するために付けている。

-shortest

入力ソースの中で「もっとも短いもの」が終わったとき終了する。

今回の場合、静止画像は上記の -loop 1 により無限ループしているため、音声が最短となる。-loop 1 がないと画像を表示して一瞬で終わってしまうし、-shortest なしは無限ループでエンコードが終わらない。

-c:v h264 -pix_fmt yuv420p

ビデオのフォーマットを指定。とりあえず X に投稿するならばこの指定がないと NG。投稿時に弾かれる。

音声は -c:a で指定できるが、下手すると環境によって聞こえないので省略(標準はaac)。

./output.mp4

出力ファイル名。

ステップ2:静止画動画を繋ぐ

さて静止画動画もいいのだけど、何かを解説したり比較したりする場合に、動かなくてもいいけど画像の切り替えくらいはほしい。ffmpeg にはスライドショーをエフェクト付きで行える機能もあるが今回はパス。

ステップ1の静止画動画を繋ぐ方法で映像を切り替える。要するに紙芝居だな。コマンドは

ffmpeg -f concat -safe 0 -i ./cc_list.txt -c copy ./output.mp4
-f concat -safe 0

連結モード。-safe 0 はファイル名の安全性がどうこう……。よく分からんがとりあえず付けとけ。

-i ./cc_list.txt

連結するためのデータ群が指定されたテキストファイル。中身はこう

file './000.mp4'
file './001.mp4'
file './002.mp4'
…
-c copy

映像と音声をそのままコピー。ゆえに劣化しないがファイルサイズが大きくなる。

大前提として、用意する静止画動画の画面サイズやフレームレートは同一にしておくこと。今回はあくまでもステップ1で作った動画を繋ぐのが目的だ。

./output.mp4

出力ファイル名。

ステップ3:動画の音声を置き換える

これで紙芝居くらいなら作れるようになった。力技で字幕付き動画にでっち上げることもできるぞ。しかし音声を無理やり繋いでいるので、BGM が途切れたりノイズが入って気になるかもしれない。なので最後に通しの音源に置き換えて仕上げる。

と言うか逆に、通しの音源をぶつ切りにして字幕の出ている長さを調整することを想定している。

本来ならもっと効率のいい方法があるだろうが、今はこれが精一杯。さてコマンドは

ffmpeg -i ./input.mp4 -i ./new_audio.opus -c:v copy -map 0:v -map 1:a ./output.mp4
-i ./input.mp4 -i ./new_audio.opus

入力ソースの動画と置き換える音源の指定。

-c:v copy

ビデオ入力をそのままコピー。劣化しないがサイズはでかい(※最後に対策する)。

音源は -c:a aac が標準。ステップ1と同様に省略。

-map 0:v -map 1:a

0 番目のソースからビデオを、1 番目のソースからオーディオを使う指定。ややこしいね。

./output.mp4

出力ファイル名。

最後に

で、作れた動画がこちら。

ffmpegで字幕を付ける機能もあるが、かなりややこしいので今回はパス。動画に別の画像や動画を重ねる機能もあったが、テロップ画像を用意して重ねるくらいなら、事前に合成しとけば済む。コレも今回はパス。

全体の流れとしてはGPT-SoVITSで読み上げ、オーダシティでミックス。それをぶつ切りにして、ペイントソフトや DTP ソフトなどで必要な字幕付き画像を作る。

001.png 001.opus、002.png 002.opus みたいな感じにね。

それを無理やり繋ぐ方法ででっち上げれば、ここまでの機能だけでも字幕付き静止画動画は作れる。手間が増えすぎてまったくお手軽じゃないが、やることが決まればスクリプトで自動化できるしな。

ところで完全な静止画動画にたいして、字幕を付けただけで容量は倍になってしまった。-c copy にした影響だな。仕上げは圧縮してよかろう。

というわけで、最後にステップ3のコマンドを調整。これなら1.2倍以下になり、ほぼ気にしなくて良いだろう。

ffmpeg -i ./input.mp4 -i ./new_audio.opus -c:v h264 -pix_fmt yuv420p -crf 25 -preset veryslow -map 0:v -map 1:a ./output.mp4
-c:v h264 -pix_fmt yuv420p

コピーをやめて。ステップ1のときと同じ設定をする。再圧縮されてしまうが、これで仕上げだ。気にするほどのことではなかろう。

-crf 25 -preset veryslow

品質を調整し圧縮率を調整できる。-crf 23 が標準で上げるほど劣化、圧縮する。

-preset veryslow は処理速度を犠牲に効率化する。

コメントを残す

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

認証コード * Time limit is exhausted. Please reload CAPTCHA.