THETA Sのmjpegをラズパイで受けてLANでUnityに配信する方法
はじめに
ラズパイでMJPG-Streamerを使って、THETA SのmjpgライブビューをLAN内に配信して、ブラウザやUnityでそれを受けて再生する話です。
RICOH THETA Advent Calendar 2015 LT大会!で以下のデモをした時の手法です。
懇親会の片隅でこんな感じのものをデモらせてもらっていました。THETA+ラズパイとGearVRを同じLANにつないでストリーミングしてテレイグ的なもの。体験していただいた方もそうでない方もありがとうございました! #thetalt pic.twitter.com/qm1fCLCQvb
— はむ! (@hammmm) January 27, 2016
とはいえ、今回の方式は以下の問題があり、実用的かというと微妙ではあります。
- Unityでの利用時にfpsが低い(これはラズパイ側の問題ではなく、主に受信側Assetのデコードが遅いため)
- 遅延が大きくなりがち(数秒程度)
- Android(Gear VR)で動かす場合にIP指定になり、いちいちIPを調べたりと面倒
でも誰かの役に立つかなということで公開しておきます。
ラズパイでMJPG-Streamerを動かす (docker利用)
まず、前回記事の手順でRaspberry Pi 2でHypriotを動かした状態を前提とします。
※なお、Hypriotでなくても、dockerがインストール済みで、UVC(USBカメラ)のドライバが入っていれば良いはずです。標準raspbianからの動作は未確認です。
そして、sshでラズパイに入ります。
$ ssh pi@pihost.local
以下の手順を実行してください。
- THETA SをLIVEモードで起動する
- THETA SをラズパイのUSBポートにつなぐ
ls /dev
として/dev/video0
というデバイス(カメラデバイス)ができているのを確認。なければTHETA Sの状態やUSB接続を確認する。docker run -p 8080:8080 -v /dev:/dev --privileged mhamanaka/rpi-mjpg-streamer-uvc:0.1
を実行する
すると、dockerイメージをダウンロードして、さらに自動的にmjpg-streamerが起動して配信がはじまります。
ラズパイのホスト名がpihost.local
だとすると、ブラウザで
http://pihost.local:8080/
にアクセスすれば、このようなmjpg-streamer の操作画面が見られます。
また、mjpeg配信のURLは
http://pihost.local:8080/?action=stream
のようになります。
※ なお、なんたら.local
はBonjourに対応していないと解決できないので、Bonjourの入っていないマシン(Windows,Android等)からアクセスする場合は、ホスト名のかわりにローカルIPで指定してください。(「ラズパイIPの調べ方」の項参照)
Docker Hubのrpi-mjpg-streamer-uvcページはこちら。
dockerイメージの中身について
上記の手順では、とあるdockerイメージを起動しただけ、という感じかと思うので、中身をお見せしておきます。といっても以下のDockerfileのとおりです。
行の最初がRUNのところはdockerイメージを作成するときに実行され、CMDのところはdockerイメージを起動するときに実行されます。要は環境を作ってからmjpg-streamerが実行されているという感じです。
FROM tukiyo3/rpi-ja MAINTAINER hammmm <ham.lua@gmail.com> RUN apt-get update RUN apt-get install -y apt-utils curl RUN apt-get install -y wget unzip RUN apt-get install -y libjpeg8-dev make gcc RUN ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h RUN cd && wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip && unzip master.zip RUN apt-get install -y cmake RUN apt-get install -y g++ RUN cd ~/mjpg-streamer-master/mjpg-streamer-experimental && make clean application input_uvc.so output_http.so CMD LD_LIBRARY_PATH=/root/mjpg-streamer-master/mjpg-streamer-experimental /root/mjpg-streamer-master/mjpg-streamer-experimental/mjpg_streamer -i "input_uvc.so -d /dev/video0" -o "output_http.so -w /root/mjpg-streamer-master/mjpg-streamer-experimental/www -p 8080"
rpi-mjpg-streamer-uvc/Dockerfile at master · hammmm/rpi-mjpg-streamer-uvc · GitHub
docker attach [コンテナ名]
で起動中のコンテナに接続すれば、コマンドの実行を止めたり、他のコマンドを実行したりすることもできるでしょう。
MJPG-Streamer自動起動の設定方法
なお、電源を入れるたびに毎回 docker run するのが面倒な場合は、以下のようにしておくと便利です。 こうしておくと、電源を入れると勝手に起動しますし、もしTHETA S(または他のWebCam)がつながっていなければ、勝手にリスタートして接続を待ってくれます。
docker run --restart=on-failure -p 8080:8080 -v /dev:/dev --privileged mhamanaka/rpi-mjpg-streamer-uvc:0.1
なお、逆に自動リスタートを止める方法ですが、対象コンテナを消せば良いので、 docker stop [コンテナ名]
のあと docker rm [コンテナ名]
みたいな感じでいけます。docker stop
だけだとゾンビのように起き上がってくるのでご注意くださいw
Unityでmjpgストリームを受ける
現状試した限りでは機種によりあまりパフォーマンスが出ませんが、 AVI Player with Playmaker actions というAsset ($49) に入っている Movie Streamerコンポーネントを利用するとmjpgストリームを再生することができます。
Unityで全天周に描画する
THETA SのUSBから取得した全天周映像ですから、以前のこちらの記事と状況は同じです。違っているのはUSBから読み込むか、ネットワークから読み込むかというところだけです。
そこで、記事で利用したWebCamDrawerスクリプトのかわりに上記AssetのMovieStreamerスクリプトを使うことができます。
プロパティは以下のようにします。
- Source :
http://pihost.local:8080/?action=stream
- Material : ThetaRealtimeEquirectangular (Both) (※コンポーネントを貼り付けたGameObjectに設定されているマテリアル)
- Play : チェックを入れておく (起動時に自動的に再生が開始します)
なお、AndroidやWindowsで実行する場合は、 pihost.local のような名前による指定ができませんので、とりあえずローカルIPを調べて、Sourceの項目はホスト名ではなくIPで指定するようにしてください。(ローカルIPは場合によって変化するので注意が必要です)
上記の画面例ではWindowsにBonjour SDKをインストール済みのため、pihost.localを参照することができます。
ラズパイIPの調べ方
なお、IPの調べ方ですが、ラズパイにsshで入ったら
$ sudo ifconfig
のようにすると、
docker0 ... eth0 ... lo ... vethef245f7 ... wlan0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet addr:192.168.1.28 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: xxxx::xxxx:xxxx:xxxx/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:128996 errors:0 dropped:801 overruns:0 frame:0 TX packets:19608 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:193015939 (184.0 MiB) TX bytes:3121760 (2.9 MiB)
のような文字列が出ますが、この場合はWi-Fiでつないでいるのでwlan0の項目を見て、192.168.1.28
がラズパイ自身のローカルIPになります。
イーサポートに有線でつないでいる場合は、eth0のところを見てください。