Chime SDKを使ってZoomライクなアプリを作ろうとしたら意外と苦戦した話

## 概要
この記事は [CA21 Advent Calendar 2020](https://adventar.org/calendars/5308) Day16の記事です。

タイトルの通り、Chime SDKを用いてZoomっぽいアプリを作ろうとしたらハマりどころが結構多くて苦戦したお話です。

本記事ではChime SDKについて、以下のことを説明します。

1. **Chime SDKとは**
2. **実装時に役に立つドキュメント**
3. **実装時にハマるポイント**
4. **通話アプリの実装にChime SDKを使うべきかどうか**

## Amazon Chime SDKを使うことになった経緯
インターン先で開発しているサービスで、これまでZoomを利用していた通話機能部分を内製化する要件が発生しました。
最初はZoom SDKを使おうとしていましたが、**UI変更が困難であること**, **ZOOMに依存した構造になってしまうこと**（たとえば使用に際してZoomのアカウントが必要となること）を懸念し、 UIの拡張性の高いChime SDKの使用を決めました。
![スクリーンショット 2020-12-15 14.51.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/bdc01e42-1071-1e28-6c0c-2e66f54049e1.png)


## Amazon Chime SDKについて
### Amazon Chime SDKとは
簡単に言えば「**通話アプリに必要な裏側の基盤をまるっとサポートしてくれる開発キット**」です。
通常zoomのような通話アプリを作ろうとすると、WebRTCなど特殊な技術の勉強が必要となります。また、人数が増えた時の拡張性などを考慮したサーバー構築なども容易ではありません。
Chime SDKを使えばそういった**煩雑な構築を完全にAWSに委ねることができます**。また逆にUIに関しては余計なサポートがないため, **自分の思い通りのUIを作ることも容易です**。

### Amazon Chime SDKを用いた通話アプリの構築
本記事では構築に関しては詳しく言及しませんが、以下記事が非常に参考になりました

[amazon-chime-sdk-js(公式)](https://github.com/aws/amazon-chime-sdk-js)
使用ケースごとにサンプルコードを書いてくれていてかなり親切. ここを見ればたいていの機能は構築できる。
[Amazon Chime SDKを試してみた](https://www.grandream.jp/blog/amazon-chime-sdk/)
日本語の記事の中では構築方法についてしっかり解説してくれている良記事。

## はまった点
このように便利に思えるChime SDKですが、実際に開発に使ってみるとかなりはまりどころがありました。本記事では自分がはまった問題点とその解決策を紹介します。

### 部屋の保存時間が限られる
開発中に「一度作ったはずの部屋が一定時間後に消えてしまう（アクセスできなくなる）」という事象が発生しました。
サポートに問い合わせてみたところ、以下の条件を満たすと、**作成したmeeting roomが自動削除されてしまう**ことがわかりました

```
1. 誰もAudio接続しないまま５分が経過した場合
2. 1人のみが接続した状態で30分以上が経過した場合
3. 1人のみがscreen shareをした状態で30分以上が経過した場合
4. meeting開始から24時間がたった場合
```

すなわち、Chime SDKではZoomのような**部屋の作り置きができない**ということです。
これを解決するには、以下図のように、**前もって別のDBにmeeting情報を保存しておき、開始時に初めてChimeでroom作成する**、などの工夫が必要です。
![スクリーンショット 2020-12-15 15.05.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/2fadfdbe-db1e-f842-6f46-161b1a3dc369.png)


### SSL化しないとうまく動かない
デプロイ後、以下のコードで本番環境のみエラーが発生する事象に遭遇しました。

``` js
//videoデバイスの設定
this.videoInputDevices = await meetingSession.audioVideo.listVideoInputDevices();
```

こちらもサポートに問い合わせてみたところ、Chime SDKを用いたアプリは**httpsプロトクルを用いた環境でないとうまく動作しない**ということがわかりました。
(上記コードが内部的に`navigator.mediaDevices`を呼び出しており、httpプロトコル化ではこれが未定義になるのが原因らしい)
だが、なぜlocalhostだと動いてしまうのかは謎...教えて強い人...!

### 自分以外の参加者の「ビデオオフ」と「退出」の判別ができない
Chime SDKでは参加者の画面On Offの検知をするために以下のようなobserverを定義します。

```js
const observer = {
        videoTileDidUpdate: async (tileState) => {
          //videoをつけた時の処理
        },
        videoTileWasRemoved: (tileId) => {
          //videoを消した時の処理
        }
      }
meetingSession.audioVideo.addObserver(observer)
```

ところが上記observer内の`videoTileWasRemoved`は該当の参加者が退出した際にも、ビデオをオフにした際にも反応してしまいます。すなわちobserver単体だと、**退出とビデオオフの状態区別ができないのです**...(この仕様のせいか、Amazon Chimeの公式アプリは、カメラをオフ専用のUIが用意されていません)

これを解決するためには、退出検知用に以下のようなコードを書く必要があります。

``` js
      //入退出処理
      const callback = async (presentAttendeeId, present) => {
        if (present) {
         //入室時処理
        } else {
          //退出処理
        }
      }
      meetingSession.audioVideo.realtimeSubscribeToAttendeeIdPresence(
        callback
      )
```
このコードは**参加者の入退室時のみ駆動し**、定義した動作を行ってくれます。
つまり、**observerのvideoTileWasRemovedにひっかかったときは問答無用で画面オフとみなす**, **退出検知のコードに引っかかった時は退出とみなす**という区別ができるわけですね。（画面オフ専用のobserverもできればつくってほしいけど...）

### 録画の仕方が特殊
ここが現状最大のWeak Pointだと思うのですが、Chime SDKは**画面および音声の録画機能**を標準サポートしていません。

代替策として、公式が[録画APIのデモ](https://github.com/aws-samples/amazon-chime-sdk-recording-demo)を提供しているのでこちらを利用することになります。
ただ、この録画APIの仕組みは「**指定したURLの画面および音声をキャプチャする**」ことですので、実際の通話アプリとは別に録画用のページを用意する必要があります。

余談ですが、このデモではec2の`t3.xlarge`が２台たちあがります。放置しているとお財布にかなりの打撃が入るので、READMEにも書いている通り、**使用後は必ず全て削除するようにしましょう。** （私はここに１ヶ月気づかず数万円ふっとばしました :moneybag: ）

## 結論　「通話アプリにAmazon Chimeを使うのは有効か？」
なんだかんだと文句は書いてきましたが、基本的には工夫すれば**通話アプリに必要なほとんどの機能は実装できるため**、かなりつかえるSDKだと感じました。
特に以下のような場合はまよわずChime SDKを使っていいのではないかと思います。

1. **特殊なUIの通話アプリを作りたい（UIのカスタマイズが自由なSDKを使いたい）**
2. **バックエンドの仕様やスペックは丸投げでいい（むしろまるなげしたい）**
3. **他のアプリに依存しない通話アプリを作りたい**


コロナの影響で、通話アプリdeveloperの需要が高まると考えられる今日この頃、皆様も是非一度試してみてはいかがでしょうか？

## PR
内定先のCyberAgentでは22卒のエンジニア採用を行っています！
https://www.cyberagent.co.jp/careers/news/detail/id=25511
皆様のご応募お待ちしております！