「ffmpeg」タグアーカイブ

ffmpeg で PinP 動画を作成する

私のドライブレコーダーは、 1 つのファイルにフロントの動画とリアの動画を入れたマルチビュー動画を作ります。これがけっこう厄介で、メーカーの専用ソフトを利用しないとうまく動画を見ることができません。そこで、ファイルにあるフロントとリアの動画を分離し、 Picture in Picture の動画にしようと思います。

説明するのが苦手なので、ソースコードを提示します。

ffmpeg -i input.AVI -map 0:0 output_front.mp4
ffmpeg -i input.AVI -map 0:1 output_rear.mp4
ffmpeg -i output_front.mp4 -i output_rear.mp4 -filter_complex "[1]scale=iw/4:ih/4 [pip]; [0][pip] overlay=main_w-overlay_w-20:main_h-overlay_h-20" PinP.mp4

3 行になってしまいましたが、入力としては input.AVI が 1 つ。中間生成ファイルとして output_front.mp4 と output_rear.mp4 の 2 つ。そして最終的なファイルは PinP.mp4 となります。当然ですが、中間生成ファイルは削除してもかまいません。ドラレコの動画は 30 秒で 1 つのファイルになっていますので、上記 3 行を複数回実行して、結合することになります。今回は、 3 行目の PinP 動画を作成する部分を中心に以下で説明していきます。

PinP 動画を作成するオプション

私自身、完全にこのオプションを理解しているわけではないので、間違った説明をしていたら、指摘してください。

まず、入力として 2 つのファイルを取ります。上記の例で行くと、 output_front.mp4 と output_rear.mp4 です。この 2 つの位置関係は重要で、最初に指定したファイルがメインになり、 2 つめに指定したファイルがオーバーレイするサブ動画になります。

※後ほど[0]、[1]という指定が出てきます。これが、最初のファイル、 2 つめのファイルを意味します。順序を逆にした場合、[0]、[1]の指定も逆転させてください。

次に、 PinP 動画のサイズを指定しましょう。[1]ファイル(この順番で行くと output_rear.mp4 )は scale=iw:ih という部分でサイズ指定します。上記の例だと、縦横ともに 1/4 にします。これを 1/2 にしたい場合は、 scale=iw/2:ih/2 とします。そして、そこにラベルを指定します。上記の例では[pip]としている部分ですが、ここは任意の文字列でかまいません。直後で指定します。

次に PinP 動画の位置を指定します。 main_w-overlay_w-20 、 main_h-overlay_h-20 が PinP 動画の位置を示します。ここでは X 座標、 Y 座標ともに 20 ピクセルを指定しているのですが、ここの指定方法は正直よく分かっていません。 40 ピクセルを指定する場合は、 40 をしてすれば良いのはわかるのですが、「 FFmpeg Filters Documentation 」ここを見ると、前半の main_w 、 main_h が 0 指定されているのがよく分かりません。ここにも数字を入れると PinP 動画がずれて ( その座標分 ) 生成されますので、オフセットと考えれば良いのかもしれません。

いずれにしても、 overlay_w 、 overlay_h のあとに数字でその生成位置を指定すると言うことのようです。座標指定の方法については後ほどまた調べて追記します。

filter_complex オプションでまとめ上げる

大きさと位置を指定したものぜんぶをダブルクォーテーションでまとめて、 filter_complex オプションでまとめ上げます。本来、ダブルクォーテーションでまとめる必要はないのですが、指定に際してスペースが必要になりますので、全体をひとまとめにする意味で、ダブルクォーテーションマークが必要になるみたいです。

最初、全て平打ちしてエラーが連発していました。よく sample を見たら“”で囲われています。なるほどそういうことかと思った次第です。

最後に出力ファイルを指定して完成です。

ffmpeg の map オプション

先のエントリで書きましたが、私のドラレコは 1 つの AVI ファイルにフロントとリアの画像をパッケージングして保存しています。分離する方法を書きますね。

複数の音声が入っている動画というのはありますね。副音声と言われるヤツです。動画でも昔マルチキャプチャーの動画がパッケージングされたものがありました。理屈は一緒ですね。ストリーム分離というキーワードで検索すると、音声の方を分離する方法があります。ただ、基本的にファイルの中のストリームを分離するのは、動画であろうが音声であろうが理屈は一緒です。

そこで、 sample.AVI( フロントとリアのストリームが同梱されたファイル ) を分離してみようと思います。以下コマンドラインでの入力です。

まず、 sample.AVI のストリーム状況を確認します。

ffmpeg -i sample.AVI

単純に入力のみを指示すると、そのファイルのストリーム状況が表示されます。こんな具合ですね。

Input #0, avi, from '2019_04_27_11_53_20_Nor.avi':
  Duration: 00:00:30.63, start: 0.000000, bitrate: 9318 kb/s
    Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p(progressive), 1280x720, 3951 kb/s, 19.10 fps, 19.08 tbr, 19.10 tbn, 38.20 tbc
    Stream #0:1: Video: h264 (High) (H264 / 0x34363248), yuv420p(progressive), 1280x720, 3932 kb/s, 19.10 fps, 19.08 tbr, 19.10 tbn, 38.20 tbc
    Stream #0:2: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
    Stream #0:3: Subtitle: none, 21 kb/s

この例だと、

  • ストリーム  #0:0 :動画 ( フロントの動画 )
  • ストリーム  #0:1 :動画 ( リアの動画 )
  • ストリーム  #0:2 :音声 ( フロントで録音された音声 )
  • ストリーム  #0:3 :不明なストリーム ( ※ )

※本来ならば、リアで録音された音声ストリームになるはずですが、多分私の環境下では結線されていないなどの理由で不明になるものと思われます。

ここまでわかってしまえば、分離するのは簡単です。 map オプションは出力するストリームを指定するものなので、リアカメラの映像のみを出力するには、

ffmpeg -i sample.AVI -map 0:1 output.AVI

これで出力されるはずです。やってみたら、できました!

後は、フロントとリアのストリームを別々に保存した動画を作るスクリプトを作ればいいだけです。「ストリーム」という単語がわからなかったので、検索してもなかなか引っかかってくれませんでした。これでリアカメラの映像も簡単に取り出せます。アプリを使った分離でも分離はできるのですが、マウスクリックやらなんやらが必要で、面倒だったんです。コマンドラインで処理なら 1 度ひな形を作ってやれば次から簡単ですし、繰り返しも簡単です。良かった。


コップを唇に持っていく間隔までには多くの失敗がある。

イギリスの諺

グラボを動画変換用に使う

iMac だとできませんでした。 AMD だとダメなのかしら? 私の探し方が悪いのかもしれませんが、 nvenc できません。 Windows10 ならできるみたいなので、やってみました。できました。

動画は mp4 です。マックユーザーなら h.264/h.265 ですよね。 wmv も再生できますが、 mp4 です。にもかかわらず、世の中にあふれる wmv 動画をダウンロードしたりするとがっかりします。

で、私は変換するわけですが、変換するのに ffmpeg というフリーソフトを使っています。 Windows10 の環境ではグラフィックスボードのエンジンを使って変換をする方法があっちこっちに乗っていますが、残念ながら Mac 環境では皆無です。 Windows10 を新しくしたので、そっちを使ってやれ。ということで、 ffmpeg のコンパイルを行いました。「 Windows 用 FFmpeg を Windows 10 でビルドする (Bash on Ubuntu on Windows) 」こちらのホームページを参考にさせていただきました。すごい環境でやってます。 Windows10 用の ffmpeg を Windows10 で動いている Ubuntu 上でコンパイルして、それを Mac からリモートデスクトップで操作している。そんなことをしました。わかります?

で、記事の内容そのままではうまくいかず、若干補正しながらでしたが無事完成。 ffmpeg を使って高速変換ができるようになりました。グラフィックスボードは GTX1050Ti を使っています。変換するのに、 10 倍とかというすごいスピードで変換できるものもあります。 h.265 は CPU を使うとかなりパワーを取られますが、 GPU を使うと CPU の使用率はそれほどでもなく高速変換が可能になります。もともと、動画ファイルを引っこ抜くのに Peppermint ( Linux )を使ったりしているので、ネットワーク上でファイルを移動する手間はかかるかなと思っていたのですが、ネットワーク越しに変換すれば変換速度よりもはるかに早いネットワーク速度があるので手間にはならないこともわかりました。

何の動画ファイルを落とすんだ? という問い合わせにはお答えできかねます。という答えで察してください(笑


知はいつも情に一杯食わされる。

ラ・ロシュフコー