これはRICORA言語班 Advent Calendarの8日目の記事です。
背景
研究に使う可能性があるのでメモとして載せておく。ローカルネットワークでの利用をまず考えている。
結論
ffmpegを使おう。
ffmpegは公式でA complete, cross-platform solution to record, convert and stream audio and video.
と名乗っているわけなので、もちろんstreamもできるわけである。
構成はこんなかんじ。あまりにも図の出来が良すぎて失神している。
+--------+
| camera |
+--------+
|
USB
+--------+ +--------+
| rspi | [wifi IEEE 802.11/?] --- *LAN* --- [wifi / ethernet] | debian |
+--------+ +--------+
現在使っているのはデスクトップつきRaspibianであり、他の人があいまいにドライバを入れた可能性もあるが、カメラは一発で認識できていて、/dev/video0
にある(もちろん、時と共に移ろいゆく)。動作確認はVLCとかで画面に映し、挙動を監視するとできる。
さて、いまRaspiberry Piで見えている画面をいい感じに同一LANの中にいるクライアントに送りたいとする。まず検討すべきことは
ffmpeg
のオプション- 配信におけるIPプロトコル(TCP / UDP どっち?)
の二点だと考えられる。もちろんffmpeg
以外のツールもあるが、いまはffmpeg
の話をしているので多分これでよい。
RaspberryPiでやるべきこと
まず、オプションがありすぎるので適当に先人のログなどを拝見させてもらおう。ありがとうございます!1つ目に関しては、特に無自覚にraspivid
が使えるかのように書かれているものの、raspivid
が使えるのは専用のカメラモジュールに限定されているようなので、注意が必要。
そのうえで、オプションを考えよう。マニュアルが長いが、まあ-i
がインプットでレート操作・動画サイズの変更などができることがわかればよい。とりあえずピクセルレートとかは最適にしてくれるっぽい(?)ので、適当なコーデックといい感じの-preset ultrafast
、-tune zerolatency
を指定することにする。動画のフォーマットはmpegts
にして、一旦は配信用にする。録画すると.ts
の拡張子のファイルが生成されるが、それをぶち込んで.mp4
のファイルを作ればよいはずなので、あまり問題はないと思っている。
コーデックに関しては、h264
よりもh265
の方が後継規格なのでよいが、まだ広まっていない(?)可能性もあるらしい。とりあえずh265
を採用して見えなかったらh264
にスイッチするという運用でもこのスケールなら問題ないように思える。付記しておくが、h266
も策定されたようなので、数年のうちにはそちらへの移行が始まる可能性が高い。
パケットサイズについてはネットワーク依存なのでよくわからないという感想が強いので、一旦は指定していないが、今後指定する可能性はある。例えばTCPはPMTUDを利用してパケットサイズを決めている。1300byteとか1000byteとかに指定するのが妥当かもしれない。
で、これらを鑑みると
ffmpeg \
-i /dev/video0 \
-vcodec libx265 \
-preset ultrafast \
-tune zerolatency \
-f mpegts \
udp://[client ip addr]:[port]&pkt_size=(...)
となる。画面の一部がほしければまた別のオプションを指定すれば良い。実際には、Client IPはもちろんクライアントのIP Addressを入力するし、ポートも同様にする。蛇足だが、こういう感じのコマンドでオプションが多くなるとNovelAIでanime girl, cute, ... {{loli, chubby}}
などのプロンプトを入力するときの気持ちになるようになってしまった。
TCP / UDPの選択に関しては、どちらでもよいはずで、どうせそんなに輻輳とかが起きないだろという希望的観測と下調べが面倒くさいという理由で真面目に調べていない。一応ヘッダーの大きさがUDPだと小さいという話はあるものの、パケットサイズが大体1000byteくらいだとして、たかだか3%くらいしか効いてこないと思うので、300x300くらいの画面サイズでの動画の画質にどれくらい影響があるかわからない。動画にはUDPだろという短絡的な選択をしてしまっている。
クライアントサイドでやるべきこと
一方、こちらはクライアント側なので、自分のipをip addr
とかで覗いてそれを書いておく。ポート番号は一応でかい数にしたほうがいい。サンプルで見たのは12000とか12001とかだが、他のサービスとポートがかぶらなければ正直なんでもいい。
クライアント側のツールもなんでもよいといえばなんでもよいのだが、まあ多機能であれば多少嬉しいのでffplay
で動作確認をして、その後VLC
を使うことにした。-fflags nobuffer
とfflags
を指定してあげるとReduce the latency introduced by buffering during initial input streams analysis.
ソースとのことで、簡単に訳すと初期のバッファリング分からの遅れを取り戻すみたいなオプションとのこと。
ffplay [client ip addr]:[port]
と打つと、しばらくしてから画面が立ち上がる。
一方、VLC
では
vlc udp://@:[port]
と入力するとVLC
が勝手に受信するように立ち上がってくれる。
VLC
を使うといい感じに録画もできて良い。このような構成で、実感としては、大体2〜3秒くらいの遅れだった。
終わりに
感想としてはかなり薄っぺらいが、こういう形で実際にポートとかIPアドレスとかを指定するとそのようなこともできるんですねという気持ちになって良い。我々はWIREDの中にいるのである。あ、いまlain見えましたよね。TCPに関しても使う可能性がある(データ取得で文句を言われたら重い腰を上げることにします。。。)ので追記したいと思っている。
また、twitterのアイコンとか見るとそれっぽいが、筆者はロリコンではない。