はじめに
本記事はJetson Nanoに接続したカメラ映像をストリーミング配信する試みである。自分がJetson Nanoを使うとき、多くの場合リモートで操作を行っている。したがってカメラ映像もリモートで見られると楽だなぁと考えていたので重い腰を上げて実施することにした。
前提条件
デバイス/dev/video0
で映像が取得できることを前提とする。
GstreamerとRTSP
一番最初に思いついたのはgstreamer
とRTSP
を使うことだ。RTSPはReal Time Streaming Protocolのことで、gst-launch-1.0
コマンドから直接使うことはできない。そのため
にあるtest-launch.c
をダウンロードしてコンパイルする。
sudo apt install libgstrtspserver-1.0-dev
gcc -o test-launch test-launch.c `pkg-config --cflags --libs gstreamer-rtsp-server-1.0`
そうするとtest-launch
が作成されるので、下記のコマンドで起動する1。
./test-launch "v4l2src device=/dev/video0 ! video/x-raw,framerate=30/1,width=640,height=480 | x264enc ! queue ! rtph264pay name=pay0 pt=96"
こうして立ち上げた後、別の端末からVLCを使ってrtsp://jetson-nano:8554/test
へアクセスするとカメラ映像を見ることができる。なおjetons-nano
の部分は私のサーバ名なので、適宜ホスト名やIPアドレスに変更する必要がある。
open -a vlc rtsp://jetson-nano:8554/test
面白い点はVLC
でアクセスすると初めてカメラが有効になる点。切断するとカメラもOFFになり、再接続するとまたONになる。
mjpg-streamer
次に試したのがmjpg-stramer
。これはオープンソースのMotion JPEGをHTTPでストリーミングするタイプ。
mjpeg-streamer+ipcam-viewでRaspberry Piのカメラの映像をAndroidへ配信する
を参考にセットアップする。
webサーバの起動のところだけ変更するため、下記のようなスクリプトを作成した。
#!/bin/sh
input=/usr/local/lib/mjpg-streamer/input_uvc.so
output=/usr/local/lib/mjpg-streamer/output_http.so
port=8080
device=/dev/video0
webroot=/usr/local/share/mjpg-streamer/www
mjpg_streamer -i "$input -d $device -r 640x480 -f 1" -o "$output -p $port -w $webroot"
これを実行したのち、http://jetson-nano:8080/
でアクセスすると次のようなページが表示される。
なるほど、これはこれで便利そうだ。ブラウザがあればアクセスできるというのは素晴らしい。
自前で作る
Jetson Nanoを使ってGPUで処理した映像はどうやってmjpg-streamer
に渡せば良いのだろう?
/dev/video0
でデバイス指定されているので、処理した映像を仮想的に作ったデバイスに紐づけるのが良さそうだ。
しかし今更CやC++で書くのがとても面倒に思えた。慣れというのは恐ろしい。できればPythonとOpenCVを使って処理したいのでPythonとのインターフェイスが欲しい。
いろいろ考えた結果、Motion JPEGをHTTPでストリーミングする部分をPythonで書けば良いんじゃなかろうかという結論に達した。作ったものは
に置いた。なんだかんだで3時間以上掛かった。こんなことなら初めからCやC++で/dev/video周辺を作るべきだったと後悔しつつ、せっかく作ったので公開することにした。
git clone https://github.com/yamamo-to/jetson_nano.git
cd jetson_nano/mjpeg_http
ディレクトリhtml/
にindex.htmlがあるのでこれを編集する。自分の場合はjetson-nano
というホスト名があるので
<img src="http://127.0.0.1:8080/camera.mjpg" />
を
<img src="http://jetson-nano:8080/camera.mjpg" />
に変更した。最後に起動する。安全を考慮してデフォルトでは127.0.0.1でバインドするので、リモートから接続するためにはbind
オプションをつけて起動する。
python3 -m mjpeg_http.server --bind 0.0.0.0
Google Chromeであればhttp://jetson-nano:8080/camera.mjpg
に直接アクセスできる。
Safariの場合は一度index.htmlを通す必要があるためhttp://jetson-nano:8080/
にアクセスする。
これでPythonとも連携可能なMJPEG Streaming環境ができた。ただし使っているモジュールはhttp.server
で製品には適さないらしい。
Warning http.server is not recommended for production. It only implements basic security checks.
まとめ
リモートでカメラ映像を映す方法として次の3種類を試した。
- GstreamerとRTSPによる配信
- mjpg-streamerによる配信
- 自作のMotion JPEG serverによる配信
今後のことを考えると/dev/video以下に仮装デバイスを実装した方が良さそうだ。
-
v4l2src
を使っているのはnvarguscamerasrc
やnvcamerasrc
がUSB接続のC920ではハングアップするため。 ↩