THETA プラグイン と WebRTC P2P で撮影アプリを作ってみた

## はじめに

こんにちは、リコーの @shrhdk_ です。

今回は WebRTC という技術を利用して、RICOH THETA V の 360° 映像を遠隔からリアルタイムに確認しつつ、THETA V のシャッターを切れるプラグインを作ってみましたのでご紹介します。

THETA 標準アプリの撮影機能を WebRTC を使って Web ブラウザだけで実現してみたという話です。

![プラグイン概要](https://qiita-image-store.s3.amazonaws.com/0/299819/575a1253-15a0-ec2b-d740-f86004e017a7.png)

ソースコード: https://github.com/ricohapi/theta-plugin-webrtc-sample

## RICOH THETA プラグインパートナープログラムについて

THETAプラグインをご存じない方は [こちら](https://api.ricoh/products/theta-plugin/) をご覧ください。
興味を持たれた方は [Twitter](https://twitter.com/thetaplugin) のフォローと [THETAプラグイン開発コミュニティ (Slack)](https://join.slack.com/t/thetadeveloper/shared_invite/enQtNzcxODI2MTk2ODg0LWY5YmU2ZTIxNGYwNzlmNWZjMWMyMWFlMzY3ZmQ3NGU3ZjZiZjI0Njk4MGIxMDU5NDJiMzQ4Y2FkNDEzYmFlNGU) への参加もよろしくお願いします｡

## WebRTC とは?

まず WebRTC とは Web ブラウザ上で音声や映像などのデータをリアルタイムにやり取りするための技術です。

Google によってオープンソース化されていて、IETF による関連プロトコルと W3C によるブラウザ対応 API の標準化が行われています。

WebRTC のライブラリは、BSD ライセンスの元でソースコードとビルドツール、および公式ビルドライブラリが配布されているので、ネイティブアプリの開発も可能です。

詳しくは公式サイトを参照してください。 https://webrtc.org/

## WebRTC P2P 接続の流れ

WebRTC P2P 接続は大まかに行って 3 ステップに分けられます。

まずはじめに、セッション情報 (SDP) を交換します。ざっくり言うと「映像送るでー コーデックは H.264 と VP9 が使えるでー!」「じゃあ H.264 でお願いしまっす m(__)m」といったやり取りをします。

つぎに、通信経路候補 (ICE Candidate) を交換します。ざっくり言うと「IPアドレス x.x.x.x のポート1111で接続できるでー」「こっちは y.y.y.y のポート2222ですわ」といったやり取りをします。

最後に、交換した情報を使って P2P 接続を確立し、セッション情報交換で決めた映像を送受信します。

セッション情報の交換や通信経路候補の交換を仲介するサーバーをシグナリングサーバーといいます。

実はこの交換方法は規定されていなくて自由です。極端な話、口頭で交換して…手でポチポチ入力して…なんてことも OK です。実際は WebSocket を使って交換することが多いです。

![P2P 接続の流れ](https://qiita-image-store.s3.amazonaws.com/0/299819/cb0f9292-9a08-4fff-caba-538d0c64edb5.png)

## プラグインを動かしてみる

前置きが長くなりましたが、サンプルをビルドして動かしてみましょう。概要だけ知りたい! という方は読み飛ばして OK です。

### THETA の Wi-Fi をクライアントモードにする

今回開発したプラグインを使うには THETA の Wi-Fi をクライアントモードにしておく必要があります。AP モードにすると肝心の WebRTC によるライブビューが動作しません。

THETA をクライアントモードにする方法はこちらの動画を参照してください。 https://www.youtube.com/watch?v=jE9_VqaVuLM

### USB 接続中も Wi-Fi が使えるようにする

本プラグインは Wi-Fi 経由で THETA にアクセスして利用します。

しかし THETA はそのままの状態では USB を接続すると Wi-Fi が無効になってしまうので Android Studio でプラグインを実行しながら Web UI を確認することができずとても不便です。

そこで [THETAのWi-FiをUSB接続中に有効化する方法](https://qiita.com/ueue/items/ecb5032c923531a45408#theta%E3%81%AEwi-fi%E3%82%92usb%E6%8E%A5%E7%B6%9A%E4%B8%AD%E3%81%AB%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)で USB 接続中でも Wi-Fi が使えるようにしておきます。

### プラグインをダウンロードしてビルドする

まず、 https://github.com/ricohapi/theta-plugin-webrtc-sample からプロジェクトをダウンロードします。

ダウンロードができたら Android Studio でプロジェクトをインポートします。`build.gradle` があるフォルダをインポートしてください。

![プロジェクトのインポート1](https://qiita-image-store.s3.amazonaws.com/0/299819/1f335301-3309-387d-33d6-27045a240fb6.png)

![プロジェクトのインポート2](https://qiita-image-store.s3.amazonaws.com/0/299819/c4160d59-8de4-e66e-ed2a-f5f4342f15da.png)

はじめにツールチェーンやライブラリのインストールがあるので時間がかかります。しばしお待ち下さい。

インポートが完了したら、デバッグモードを有効にした THETA V を接続して、ツールバーの実行ボタンを押してください。プラグインのビルドと実行が始まります。

![プラグインを起動](https://qiita-image-store.s3.amazonaws.com/0/299819/0f6ae38a-e18c-c604-ba62-a92e78101539.png)

ビルド中に以下のようなエラーが出た場合は、エラーメッセージに従ってツールチェーンをインストールしてください。

![Failed to find Build Tools revision 28.0.3](https://qiita-image-store.s3.amazonaws.com/0/299819/ef758bb4-ae6c-88cf-d264-1891d303f8ca.png)

ビルドが成功してプラグインが実行されると、THETA からピピピッと音が鳴って、即終了します。これはプラグインに権限が設定されていないのが原因ですので、アプリ設定から権限を付与します。 THETA の仮想画面は [Vysor で操作](https://qiita.com/KA-2/items/9dce1a165fcf0203b1cb)できます。

<img alt="権限設定" width="360" src="https://qiita-image-store.s3.amazonaws.com/0/299819/16c85193-f38a-ba13-835c-ce8661264eef.jpeg"/>

以下のコマンドでも設定できます。

```shell
$ adb shell pm grant com.theta360.pluginapplication.webrtc.sample android.permission.CAMERA 
$ adb shell pm grant com.theta360.pluginapplication.webrtc.sample android.permission.RECORD_AUDIO
```

権限設定は初回のみ必要です。また、実際にプラグインストアで配布する際は、自動設定されるようになっています。

設定ができたら、改めてツールバーから実行しましょう。

![プラグインを起動](https://qiita-image-store.s3.amazonaws.com/0/299819/0f6ae38a-e18c-c604-ba62-a92e78101539.png)

起動するとこんな画面になります。

<img alt="プラグイン画面" width="360" src="https://qiita-image-store.s3.amazonaws.com/0/299819/8b0ddcdc-deae-d924-acbe-f7e638ede096.jpeg"/>

この例では 192.168.1.5:8888 で HTTP サーバーが起動しています。 IP アドレスは環境によって異なります。

### アプリを使ってみる

プラグインが起動できたら、 THETA と同じネットワークにいる端末の Web ブラウザから http://192.168.1.5:8888 にアクセスします。 IP アドレスはネットワーク環境によって異なります。

今回は Nexus 5X 上の Google Chrome からアクセスしました。アクセスに成功すると次のようなページが表示されます。

<img alt="Web ブラウザの画面" width="360" src="https://qiita-image-store.s3.amazonaws.com/0/299819/e4b1e89a-ff65-e999-02a7-a3bcbda37034.png"/>

部屋が汚いのでモザイクをかけていますが、実際は鮮明なライブビューが表示されています。

これで、動作確認は成功です! 標準アプリのようにオプションを設定したり、シャッターを切ったりできます。

## プラグインの構成

今回作ったプラグインの構成を紹介します。水色のブロックがプラグインで、黄色のブロックが今回実装した部分です。

特徴として、シグナリングサーバー (WebSocket サーバー) と Web サーバーをプラグインの中に持っています。
外部のサーバー無しで THETA に直接アクセスするだけで Web アプリとして使える様になっています。

![ブロック図](https://qiita-image-store.s3.amazonaws.com/0/299819/45c8c97b-aefa-4ac3-6979-d5199afd341d.png)

### シグナリングサーバー

シグナリングサーバーは前述のとおり WebRTC のセッション情報 (SDP) と通信経路候補 (ICE Candidate) を交換するサーバーです。
実態はシンプルな WebSocket サーバーです。受信したメッセージを送信者以外にブロードキャストするように作られています。

[Java WebSockets](https://github.com/TooTallNate/Java-WebSocket) というライブラリを利用しています。

実装は[SignalingServer.java](https://github.com/ricohapi/theta-plugin-webrtc-sample/blob/master/app/src/main/java/com/theta360/pluginapplication/webrtc/sample/network/SignalingServer.java) にあります。

### Web サーバー

Web サーバーは Web ブラウザ上で動かす アプリファイル (HTML/CSS/JavaScript) の配信をしています。また、撮影設定の変更やシャッター動作といったコマンドの受付を担っています。

[AndroidAsync](https://github.com/koush/AndroidAsync)というライブラリを利用しています。

実装は[WebServer.java](https://github.com/ricohapi/theta-plugin-webrtc-sample/blob/master/app/src/main/java/com/theta360/pluginapplication/webrtc/sample/network/WebServer.java)にあります。 

アプリファイル (HTML/CSS/JavaScript) は assets フォルダにいれて APK に同梱しています。
また Web サーバーを起動するために THETA 独自の設定ファイルである `settings.json` も同梱しています。
このあたりの解説は以下の記事が詳しいです。

[THETAプラグインのWeb UIの実装方法【THETA プラグイン開発】 - Qiita](https://qiita.com/3215/items/d156307dfadd7dc2fbf6)

### WebRTC ライブラリ

WebRTC のライブラリとして [google-webrtc](https://bintray.com/google/webrtc/google-webrtc) を利用しています。セッション情報 (SDP) の生成や映像のエンコード・デコード、ストリーミングはこのライブラリで処理されます。

THETA のカメラにはいくつか独自の設定が必要なため、それらを設定する THETA 用の拡張を追加しています。

このあたりの事情や WebRTC ライブラリの使い方については以下の記事で解説しています。

[THETA V 単体で 360° 映像をリアルタイム配信する - Qiita](https://qiita.com/shrhdk_/items/fa7bb0feab443e3037e8)

### THETA 基本アプリ

プラグインではなく、普通の THETA としての機能を実現しているアプリです。[THETA API v2](https://developers.theta360.com/ja/docs/v2.1/api_reference/) (プラグイン API ではなくWeb API の方) のサーバーにもなっています。

今回はプラグインから THETA API v2 を呼ぶことで撮影設定の変更やシャッター動作を実現しています。

### MainActivity

周辺ブロック制御するのが MainActivity です。これがプラグインのエントリポイントです。セッション情報の送受信や撮影設定を仲介したり、IP アドレスや動作状況を画面に表示したりします。

### アプリ (フロントエンド)

フロントエンドは HTML + CSS + JavaScript のベーシックな構成で、JavaScript 部分も jQuery を使った素朴なものになっています。タッチ操作スライダーの実装に [Swiper](https://idangero.us/swiper/) を利用しています。

GUI の提供と シグナリングサーバーとのやり取り、Webサーバーへのコマンドの送信、WebRTC の制御を担っています。

## まとめ

* ライブビュー機能つきの撮影アプリプラグインを作成した。
* WebRTC を使うことで、ブラウザ上で動く Web アプリとして実現した。
* P2P モードを使うことで外部サーバー無しで動くようにした。