WebRTC Native Client Momo から Amazon Echo Show 5 に配信してみよう

# はじめに

これは [WebRTC Meetup Tokyo #22](https://atnd.org/events/108171) の発表資料です
(2019.09.01現在の情報です）

# 自己紹介

- がねこまさし @massie_g
- WebRTC Meetup Tokyo スタッフ
- インフォコム株式会社所属 

---

# やりたいこと

「○○、玄関の様子見せて」
↓
玄関外の様子が、画面付きスマートスピーカーに映し出される

---

# 先にオチ

- 部分的に実現。声だけではできず
- 何回かタッチ操作が必要

![IMG_4307.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19403/b720fe8f-1dd9-4599-6a0e-3f24f4708646.jpeg)


---

# 今日の題材

- OSSのWebRTC Native Client Momo
- WebRTC シグナリングサーバー Ayame / Ayame Lite
- Amazon Echo Show 5

※Momo, Ayame については非公認です。記述に誤りを発見した場合のクレームは私(@massie_g)まで

---

# 1. WebRTC Native Client Momo

- 株式会社時雨堂を中心とし協力者の方々が開発、OSSとして公開(Apache License 2.0)
    - https://github.com/shiguredo/momo
- ブラウザなしで様々な環境で動作する WebRTC ネイティブクライアント
    - libwebrtcを利用（ビルド環境を含む）
    - 環境により、H.264 ハードウェアエンコーダーをサポート
    - makeで簡単にビルド可能、ただしディスクと時間と覚悟が必要
        - 手元のマシンで20GB、20分、ファンが回りっぱなし
    - macOSやUbuntu上で、Raspberry Pi 向けバイナリの生成が可能
        - Dockerを利用したクロスビルド
        - Dockerが利用するディスク容量を増やしておくと吉

<img width="494" alt="docker_disk.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19403/c3e05742-90c7-7fc7-96bc-1f19da63177d.png">

---

# （続）WebRTC Native Client Momo

- 動作環境
    - Raspbian Buster ARMv7 / ARMv6
        - バイナリも配布
    - Ubuntu 18.04 x86_64 / ARMv8
    - Ubuntu 16.04 x86_64 ROS Kinetic / ARMv7 ROS Kinetic
    - macOS 10.14 x86_64
    - ※Windows版ビルドツールは有償提供とのこと
- 実行モード
    - test ... 動作確認用のP2Pモード
        - momo自身が配信クライアントと、Webサーバー/シグナリングサーバーも兼ねる
    - ayame ... シグナリングサーバーAyameに対応したP2Pモード。momoは配信クライアントのみ
    - sora ... 商用SFU Soraの前提としたモード。momoは配信クライアントとして動作
- ※ momo 自体は長時間の安定して稼働
    - 72時間動かしてみたが、大丈夫
    - ただし、USBカメラがめちゃくちゃ熱くなってしまった

---

# デモ1

- macOS momo を利用
    - testモードで起動

```:momoをtestモードで起動
$ ./momo --no-audio --port 8080 test
```

- ブラウザで開く
    - http://_momoを実行しているipアドレス_:8080/html/test.html
    - ※getUserMedia()は使っていないので、http://～ でもOK

---

# 参考： momo をビルドしてみる

MacでRaspberry Pi 3用のmomoをビルド（要Docker）

```
$ git clone https://github.com/shiguredo/momo.git
$ cd momo
$ cd build
$ make raspbian-buster_armv7
// ... ここで 數十分〜数時間
make[1]: Leaving directory '/root/momo'
# ビルド後に ./momo p2p で動作確認できるようにしたいので、生成されたバイナリをルートディレクトリにコピーする
cp _build/raspbian-buster_armv7/momo momo
$ cd ..
$ ls momo
momo*
```

- バイナリは momo/ 直下にコピーされる
- _build/raspbian-buster_armv7/ に momo* と libwebrtc.a （ライブラリ）が生成


---

# momo 利用事例

こちらで色々紹介されています
https://gist.github.com/voluntas/51c67d0d8ce7af9f24655cee4d7dd253#id12

- ラズパイとWebRTCで動物の死活監視ができるようにした話 - ( ꒪⌓꒪) ゆるよろ日記
    - https://yuroyoro.hatenablog.com/entry/2019/08/14/183400
- Raspberry Pi 3Bでほぼリアルタイムにネット経由で動かせるラジコンを作った。
    - https://twitter.com/shirokunet/status/1135465368636387328
- （改造例）RaspberryPi Zero WでエレキットのロボットアームをWebRTCで遠隔制御できるようにしたよ
    - https://twitter.com/tnoho/status/1159386099178823680

---

# 2. シグナリングサーバー Ayame / Ayame Lite

- Ayame … 1対1のP2P専用の、シグナリングサーバー
    - OpenAyameプロジェクトとしてOSS公開（時雨堂としてではなく）
        - https://github.com/OpenAyame/ayame
    - goで実装
    - 各種クライアント用のSDK/サンプルあり
        - Web用SDK https://github.com/OpenAyame/ayame-web-sdk
        - iOS用SDK https://github.com/OpenAyame/ayame-ios-sdk
        - Android用SDK https://github.com/OpenAyame/ayame-android-sdk
    - 双方向、および片方向配信に対応
- Ayame Lite ... 時雨堂がAyameをホストしているシグナリングサービス(β)
    - https://ayame-lite.shiguredo.jp/beta
    - 登録不要で、鍵なしのルームが利用可能（STUNもあり）
    - 登録すれば、鍵付きのルームとTURNサーバー(ポートは3478)が利用可能

---

# デモ2

- Raspbian momo を利用
    - ayame モード
- Ayame Lite （登録なし）を利用
- ブラウザ側には ayame-web-sdk を利用
    - SDK ... https://github.com/OpenAyame/ayame-web-sdk
    - SDKサンプル ... https://github.com/OpenAyame/ayame-web-sdk-samples

```:momoをayameモードで起動
$ ./momo --no-audio ayame wss://ayame-lite.shiguredo.jp/signaling your_room_id
```

- ブラウザで開く（上記サンプルを拝借）
    - https://mganeko.github.io/ayame4echoshow/recvonly.html?roomId=your_room_id

---

# 受信側サンプルコード

https://github.com/OpenAyame/ayame-web-sdk-samples/blob/master/recvonly.html を拝借

```html:recvonly.htmlの抜粋
<script src="./ayame.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.7.0/qs.min.js"></script>
<script src="./main.js"></script>
<script type="text/javascript">
  const options = Ayame.defaultOptions;
  options.video.direction = 'recvonly';  // 受信のみを指定
  options.audio.direction = 'recvonly';  // 受信のみを指定
  const conn = Ayame.connection(signalingUrl, roomId, options, true);
  const startConn = async () => {
    await conn.connect(null, { key: signalingKey });
    conn.on('open', ({ authzMetadata }) => console.log(authzMetadata));
    conn.on('disconnect', (e) => console.log(e));
    conn.on('addstream', (e) => {
      document.querySelector('#remote-video').srcObject = e.stream;
    });
  };
</script>
```

---

# ayame-sdk-web を覗いてみる

src/connection/base.js

recvonly の指定 → addTransceiver()

```js
const videoTransceiver = pc.addTransceiver('video', { direction: 'recvonly' });
```

videoコーデックの指定 → setCodecPreferences()

```js
videoTransceiver.setCodecPreferences(videoCodecs); // 'VP8' | 'VP9' | 'H264'
```

※setCodecPreferences()が使えない場合は、SDPを直接いじっている様子

---

# Ayame 利用事例

- みなさん、筋トレにはWebRTCですよ！！！ これでプランクの姿勢をチェックできる！
    - https://twitter.com/koedameiro/status/1167724758009401345

---

# 3. Amazon Echo Show 5

- 画面付きスマートスピーカー （= スマートディスプレイ）
- 2019年6月末販売開始の普及版。9980円
- OS: Fire OS （Androidのフォーク）
- 5インチスクリーン 960 x 480 (2:1)
- マイク、スピーカー、カメラ付き
    - ミュートボダン、物理カメラシャッター
- 「アレ〇〇」で始まる声で操作
    - タッチスクリーンでも一部操作可能

![Iechoshow5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19403/05e14374-9368-d3f7-c76d-f739ba1bce49.jpeg)

---

# Echo Show 5 とブラウザ

2つのブラウザが内蔵

- Firefox for Echo Show
    - https://support.mozilla.org/en-US/kb/firefox-echo-show
    - https://github.com/mozilla-mobile/firefox-echo-show
    - Fire HD 向けなどと同系統
    - 複数タブ、複数ウィンドウは使えない
    - 「アレ〇〇、Firefox起動」で起動
- Silk
    - Chromiumベース


---

# Firefox for Echo Show と WebRTC

- mediaDevices.getUserMedia() → 使えない（ブラウザからマイク/カメラを認識できない）
    - http:// の場合 .. NotSupportedError: Only secure origins are allowed
    - https:// の場合 ... NotAllowedError: Permission denied
- RTCPeerConnection
    - RTCPeerConnection はある。P2Pでの通信は可能
    - Videoコーデック
        - H.264 ... NG
        - VP8, VP9 .. OK
    - Audioコーデック
        - Opus ... OK
    - Multistream .. 動く（複数 videoTrack 可能）
        - RTCPeerConnection.ontrack()も動く
        - RTCPeerConnection.addTrack()も存在、動作は未確認
    - Unified-Plan
        - 明示的指定が必要 ... new RTCPeerConnection({sdpSemantics: 'unified-plan'});
        - RTCPeerConnection.addTranceiver() ... Unified-Planを明示的に指定した場合のみ利用可能
            - 指定しないと例外発生
        - RTCRtpTransceiver.setCodecPreferences()は無し

---

# Firefox for Echo Show メディア関連

- video.srcObject ... あり
- video.play() ... ユーザージェスチャーが無いと再生できない
- canvas.captureStream() ... あり。MediaStream が取得できる

---

# デモ3

- Raspbian momo を利用
    - ayame モード
- Ayame Lite （登録なし）を利用
- Amazon Echo Show で受信
    - 「アレ〇〇、Firefox起動」
    - URLをタッチ入力 or ブックマークから
        - https://mganeko.github.io/ayame4echoshow/recv4echoshow.html?roomId=your_room_id
    - 「接続」ボタンをタッチ
    - 「最大化」
- ※ソースはこちら https://github.com/mganeko/ayame4echoshow

---

# ayame-web-sdk の改造

sdpSemantics: 'unified-plan' を明示的に指定

```js:
 class ConnectionBase {
    // ... 省略 ...
    constructor(signalingUrl, roomId, options, debug = false) {
      // ... 省略 ...
      this._pcConfig = {
        iceServers: this.options.iceServers,
        sdpSemantics: 'unified-plan'  // <-- ここを追加
      };
      // ... 省略 ...
   }
   // ... 省略 ...
   _createPeerConnection() {
     const pc = new window.RTCPeerConnection(this._pcConfig);
     // ... 省略 ...
   }
   // ... 省略 ...
}
```

---

# Alexa スキルを作れるか？

- 画面つきスキルが作れる
    - 決まった部品が配置可能→JSONでエクスポート
    - 異なるデバイスで、それなりに表示されるように
- 任意のHTML/JS/CSSが使えるわけでは無い
    - WebRTCをそのまま利用することはできない
- 特定のURLを直接ブラウザで開くスキルも、今のところできない

→ 今は声だけでWebRTCを受信するスキルは作れない

<img width="800" alt="alexa_screen.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19403/e01a471b-6d1a-16b1-9ab9-6a78df81b1c2.png">




---

# 余談： Silkブラウザの場合

- Silkブラウザの起動
    - 試した限り、音声コマンドで明示的にSilkブラウザを起動することできない
    - デフォルトブラウザにSilkを選択し、ブラウザが必要になる動作を間接的に指示する必要あり
        - YouTubeの再生など
- Silk と getUserMedia()
    - http:// の場合 .. なにも起きない（例外も起きない）
    - https:// の場合 ... カメラ/マイクのアクセス許可のダイアログが表示されるが、操作できない
        - ボタンを押しても反応しない
        - ... 惜しい
- Silk と RTCPeerConnection
    - P2P で映像の受信、表示は可能
    - Firefoxとは異なり）H264も利用可能
    - Multistream, Unifiled-Planは未確認


---

# 余談2： Google Nest Hub の場合

- いわゆる「Webブラウザ」は搭載されていない
- WebRTCは使えない
- YouTube 再生機としては、とても優秀

![nesthub.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19403/69f2992d-a36d-2531-e327-dfb09445313f.jpeg)

---

# まとめ

- momo を使うと、手軽にブラウザを使わずに配信ができる
- Ayame Liteを使うと、1対1限定だけど、簡単にWebRTC通信ができる
- Amazon Echo Show 5でも、WebRTCで受信ができる

ブラウザ以外でも、いろんなデバイスでWebRTCは使える！

---

# 参考

- Windows用 libwebrtc(webrtc.lib)のビルド
    - https://github.com/shiguredo/shiguredo-webrtc-windows
- Unity社公式プラグイン
    - https://github.com/Unity-Technologies/UnityRenderStreaming
    - Windows x64前提、Unityからの配信
- skyway-webrtc-gateway
    - https://github.com/skyway/skyway-webrtc-gateway
    - 既存のRTPデバイス、UDPデバイスをWebRTCを使ってSkywayに連携
    - Raspberry Piもサポート