ffmpegで動画の再生とデスクトップのキャプチャー

2023/06/25に公開

はじめに

ffmpeg は動画の変換に使われるソフトで動画の切り取り、変換、音声の抜き取りといった動画編集には欠かせないソフトです。コマンドラインで動かすのでハードルが高い感じがしますが、コマンドラインだからこそ自動化ができるわけです。筆者は動画の編集や変換というエリアには疎く素人ですのでffmpegが得意とするところはよくわかっていませんが、ffmpegで余り知られていない(と思っているのは筆者だけか?) 動画の再生やデスクトップのキャプチャーといったことをやってみたのでここにその方法を説明します。自分用のメモでもありますが、シェアさせてもらいます。

ffmpegコマンドの概要

ffmpegの使い方はごく単純で、次のようになっています。

ffmpeg 入力のオプション -i 入力ファイル 出力のオプション 出力のオプション

inputのoptionとoutputのoptionにどのようなものがあるかはここでは触れません。というかよく知りません。optionが何もなければ単純に

ffmpeg -i inputfile outputfile

でinputfileをoutputfileに変換してくれます。実に単純です。例えば、

ffmpeg -i input.mp4 output.avi

で mp4 を aviに変換してくれるというわけです。
ここでinputfileとかoutputfileのところにfileではなくurlとか画面を指定することができます。

入力ファイルにURLを指定する

私はraspberry piにusbカメラをつけてmotionで監視カメラの画像をlan内に配信しています。lan内のPCからはweb browserに監視カメラの画像を配信しているraspberry piのip addressとportをurlに指定して画像をみることができます。 raspberry piのip addressが例えば、
192.168.1.200 なら motionが配信するdefaultの portは8081なので、browserのurlをいれるところに

http://192.168.1.200:8081

をいれてやれば監視カメラの映像を見ることができます。ffmpegでもinputfileにstream配信しているurlを指定することができます。例えば、

ffmpeg -i http://192.168.1.200:8081 surveillance.mp4

とやるとraspberry piの画像を surveillance.mp4に録画することができます。
入力ファイルのところはurlだけでなくdesktopでもできます。この場合は、入力のオプションが必要で、"-f gdigrab"を指定します。

ffmpeg -f gdigrab -i desktop desktop.mp4

まずは再生

筆者は実は以前再生にmplayerを使っていました。何に使っていたかというと Raspberry piにusbカメラをつけて motion をインストールして監視カメラを設置していたのですが、そのモニターにmplayerを使っていたわけです。Raspberry piを使ってX-serverを立ち上げずにmotionの動画を見れないかと探していたらmplayerにいきついたわけです。X-serverを立ち上げるのであれば vlc などのアプリを使えばいいのでしょうが、ところがそのmplayerが壊れてしまったのです。どこが壊れたのかわかりませんが(ソフトが壊れたのでしょうがOSなのかアプリなのかわかりません。) とにかくモニターに映らなくなってしまったわけです。仕方がないのでOSを再度インストールし、mplayerもインストールしたのですが、mplayerでframe bufferに動画を書き込む方法を失念してしまったのです。それでしかたがなくwebでいろいろ調べていたらffmpegで動画の再生ができることを知りました。
motionでストリーム配信している場合はweb browserで動画を見ることができます。 motionが走っているマシンのip addressが例えば、 192.168.2.xxx だったとすると、browserで
http://192.168.2.xxx:8081
を指定すればカメラの映像を見ることができます。これをffmpeg でFrame bufferに書き込ませるには、

ffmpeg -i http://192.168.2.xxx:8081 -pix_fmt rgb565  -f fbdev /dev/fb0

とやります。
/dev/fb0 がframe bufferなのですが、環境によって変わってくるかもしれません。筆者の場合は /dev/fb0 でした。webで調べると/dev/fb0が最初のframe bufferで /dev/fb1 が次のframe bufferとの説明がありました。ただframe bufferなので当然stdoutに何か書かれたりするとその文字がでてしまいます。ffmpeg が動画をせっせと書きながら同時にメッセージもstdout もしくは stderrorに書き込んでしまうのでせっかくの動画が文字で上書きされてしまいます。それをさけるため筆者はリモートからsshでlog inし、そこで上記のコマンドを投げています。そうすれば、ffmpegが出すメッセージはsshしているマシンに出力されるのでframe bufferには上書きされません。しかしずっとsshでlog in しておくわけにはいかないので screen を利用しています。つまりscreenにはいって上記のコマンドを投げてscreenをdetachするわけです。screen については ここ に説明があります。
-pix_fmt rgb565 ですが、deprecated というwarningが出ているのであまりよろしくないですが、残念ながら筆者にはどうするのが一番よいか分かっていません。今のところ動画に問題はないのでまあいいかというレベルです。(ググってみたところ無視してよいとのことでした。)
以上はlinuxでの話です。windowsではどうするか。これも調べてみました。私はwindows11を使っていますが、調べようとした時点ではすでにwindowsでffmpegは使える状態でした。ffmpegをwindowsにどうやってインストールしたのか覚えていませんが、というかインストールをしたという記憶すらないのですが、たぶん最初からはインストールされていないでしょうね。ですのでインストールの方法については説明できません。リナックスなら apt-getでインストールしたと思いますが、windowsではscoopでインストールできるかどうかもわかりません。それはともかくwindowsでmotionで配信している動画は次のコマンドで再生できました。ちょっと感動しましたね。

ffmpeg -i http://192.168.2.xxx:8081  -pix_fmt yuv420p -s 640x480 -f sdl "title Name"

LinuxではX の力を借りずにframe bufferに直接出力できますが、windowsでは当然そのようなことはできないでしょうね。それはともかく、Linuxでx-serverを立ち上げている場合はどうするのでしょうね。実はこれもwindowsと全く一緒でいけるのではと思ってます。つまり、

ffmpeg -i http://192.168.2.xxx:8081  -pix_fmt yuv420p -s 640x480 -f sdl "title Name"

これはwindowsのwsl2でやってみたらうまくいきました。純粋なlinux machineでは試していませんができるのではないかと思ってます。

画面のキャプチャー

ffmpegの-fオプションはデバイスの指定です。-i が入力の指定でオプションなしで指定するのが出力先の指定です。ですので

ffmpeg -i http://192.168.2.xxx:8081  -pix_fmt yuv420p -s 640x480 -f sdl "title Name"

は入力に urlである http://192.168.2.xxx:8081 を指定し、デバイスに sdl をそして出力に "title Name" を指定していることになります。-pix_fmtはピクセルのフォーマットの指定ですね。
このデバイス指定のところにキャプチャーデバイスを指定し、入力のところにデスクトップを指定すれば画面のキャプチャーができます。

ffmpeg -f gdigrab -i desktop -framerate 2 out.mpg

おまけ スクリーンショット

windowsで動画ではなくスクリーンショットもとれます。 -frames:v 1 を出力の指定の前に指定します。

ffmpeg -f gdigrab -i desktop  -frames:v 1   out.png

でdesktopのスクリーンショットがout.pngに取られます。

リンク

この記事はここを参照して書きました。
分かりやすく解説してくれているのはここ

Discussion