THETA Sのmjpegをラズパイで受けてLANでUnityに配信する方法

はじめに

ラズパイでMJPG-Streamerを使って、THETA SのmjpgライブビューをLAN内に配信して、ブラウザやUnityでそれを受けて再生する話です。

RICOH THETA Advent Calendar 2015 LT大会!で以下のデモをした時の手法です。

とはいえ、今回の方式は以下の問題があり、実用的かというと微妙ではあります。

  • Unityでの利用時にfpsが低い(これはラズパイ側の問題ではなく、主に受信側Assetのデコードが遅いため)
  • 遅延が大きくなりがち(数秒程度)
  • Android(Gear VR)で動かす場合にIP指定になり、いちいちIPを調べたりと面倒

でも誰かの役に立つかなということで公開しておきます。

ラズパイでMJPG-Streamerを動かす (docker利用)

まず、前回記事の手順でRaspberry Pi 2でHypriotを動かした状態を前提とします。

※なお、Hypriotでなくても、dockerがインストール済みで、UVC(USBカメラ)のドライバが入っていれば良いはずです。標準raspbianからの動作は未確認です。

hammmm.hatenablog.com

そして、sshでラズパイに入ります。

$ ssh pi@pihost.local

以下の手順を実行してください。

  1. THETA SをLIVEモードで起動する
  2. THETA SをラズパイのUSBポートにつなぐ
  3. ls /dev として /dev/video0 というデバイス(カメラデバイス)ができているのを確認。なければTHETA Sの状態やUSB接続を確認する。
  4. 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 の操作画面が見られます。

f:id:hammm:20160204012521p:plain:w300

また、mjpeg配信のURLは

http://pihost.local:8080/?action=stream

のようになります。

※ なお、なんたら.localBonjourに対応していないと解決できないので、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から読み込むか、ネットワークから読み込むかというところだけです。

hammmm.hatenablog.com

そこで、記事で利用したWebCamDrawerスクリプトのかわりに上記AssetのMovieStreamerスクリプトを使うことができます。

プロパティは以下のようにします。

  • Source : http://pihost.local:8080/?action=stream
  • Material : ThetaRealtimeEquirectangular (Both) (※コンポーネントを貼り付けたGameObjectに設定されているマテリアル)
  • Play : チェックを入れておく (起動時に自動的に再生が開始します)

f:id:hammm:20160204021618p:plain

なお、AndroidWindowsで実行する場合は、 pihost.local のような名前による指定ができませんので、とりあえずローカルIPを調べて、Sourceの項目はホスト名ではなくIPで指定するようにしてください。(ローカルIPは場合によって変化するので注意が必要です)

上記の画面例ではWindowsBonjour 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のところを見てください。