Amazon Chime SDK新機能を使ってホワイトボードを実装した件

` この記事はこちらでも紹介しています。 `
https://cloud.flect.co.jp/entry/2020/06/01/115652

前回は、Amazon Chime SDKのVirtual背景の作り方についてご紹介しました。

https://qiita.com/wok/items/962929e63bc98e4033b9

今回も引き続きAmazon Chime SDKのお話をしたいと思います。


さて、先日Amazon がAmazon Chime SDKの新機能追加を発表したのをご存知でしょうか。

https://aws.amazon.com/jp/about-aws/whats-new/2020/05/amazon-chime-sdk-data-messages-real-time-signaling/

本機能は、Amazon Chimeで使われているデータ通信路を間借りすることで、会議の参加者間でデータメッセージのやり取りを可能にする機能です。発表にも書かれているとおり、これにより例えば会議室参加者間でホワイトボードを共有したり、絵文字のやり取りを簡単に行えたりします。また、活用の仕方によっては、参加者のミュートを強制するなど会議室の状態制御を行うことも可能になります。

ということで今回は、早速この機能を使ってホワイトボードを作ってみましたのでご紹介したいと思います。

今回作ったホワイトボードの挙動はこんな感じです。

![20200529102321.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/c1af7091-c4ea-8ac9-2ed6-4fce9cdeb7a6.gif)

### Amazon Chimeとシグナリング
今回のAmazon Chime SDKの追加機能は、もともとAmazon Chimeで使われているシグナリング通信を間借りして実現されているようです。Amazon Chimeのビデオ会議はWebRTCという技術を用いて実現されていますが、この制御を行う際に用いられている通信がシグナリング通信です。具体的には、WebRTCではブラウザ間でP2Pの通信を行うのですが、この通信を開始するために相手の宛先を特定したり、暗号通信の鍵交換をしたりするときに用いられます。また、P2P通信と言ってもFirewallを越えた通信を行う場合にはTURNという中継サーバを経由する必要がありますが、こういった経路に関する情報交換もシグナリング通信で行われます。

WebRTCの全体像とシグナリングの関係は[こちらのページ](https://jp.vcube.com/sdk/blog/webrtc-general-server-configuration-signaling-turn-sfu.html)が詳しいので、詳しく知りたい方は参照ください。

Amazon Chimeは、様々なネットワーク環境下においてもビデオ会議を簡単に開始できるように、マネージドな中継サーバやシグナリング通信の通信路を提供しています。今回追加された機能はこのシグナリングを行うマネージドな通信路を活用して、任意のデータメッセージをやり取りできるようにしています。なので、開発者はメッセージング用サーバを用意する必要がなく、簡単にビデオ会議システムに共有ホワイトボードなどを追加することができます。

### API概観
新たに提供されたメソッドは下記の３つです。

本機能では、Topicというタグをつけてデータメッセージに送受信します。

まず、各クライアントではTopic毎に処理を定義したコールバック関数を登録しておきます。そして、送信側がTopicと共にデータメッセージを送信すると、そのデータメッセージを受け取ったクライアントはTopicに応じたコールバック関数を呼び出し処理を行います。内部処理、特にデータの流れの詳細は不明ですが、おそらく一般的な[publish/subscribeモデル](https://ja.wikipedia.org/wiki/%E5%87%BA%E7%89%88-%E8%B3%BC%E8%AA%AD%E5%9E%8B%E3%83%A2%E3%83%87%E3%83%AB)で動いていると思われます。

今回使用してみて、とても使いやすい機能だと感じました。

なお、本機能では、データメッセージのPublisherが、そのデータメッセージのTopicをsubscribeしていても、そのデータメッセージを受信できないので、注意が必要かもしれません。
私は、PublisherとSubscriberがお互いの関係性を全く無視できるようにするのが、publish/subscribeモデルの利点だと思っているので、PublsherとSubscriberが同じソフトウェア(セッション)だとデータを受信できないというのは、ちょっとだけ違和感がありました。（個人的には、未だに自分のプログラムのバグかも？とも思ってます。）今回のホワイトボードのようなリアルタイムにPublisherのUIに情報を反映する必要があるものについては、受信時のフィルタリングをしなくてよく、ありがたいとも言えますので、個人の感じ方次第だとは思いますが。


<i>新たに提供されたメソッド</i>

* データ送信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/5ee8d2fc-fe14-b5af-ecf6-578e0b507209.png)
https://aws.github.io/amazon-chime-sdk-js/interfaces/audiovideofacade.html#realtimesenddatamessage

* データ購読登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/7328e982-968b-a044-d5ad-0f0bd09b0499.png)

https://aws.github.io/amazon-chime-sdk-js/interfaces/audiovideofacade.html#realtimesubscribetoreceivedatamessage

* データ購読解除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/6c4ede2a-0655-89c6-e375-f652a82151f9.png)

https://aws.github.io/amazon-chime-sdk-js/interfaces/audiovideofacade.html#realtimeunsubscribefromreceivedatamessage



### 共有ホワイトボードの処理の概要
今回作成した共有ホワイトボードの大まかな処理の流れは次のとおりです。

1. Publisherのブラウザのキャンバス(HTMLCanvasElemnt)上でマウスイベント/タッチイベントを検出し、座標を特定
1. Publisherのキャンバス上に描画
1. 座標をデータメッセージとしてBroker(Chime)に送信 (realtimeSendDataMessage)
1. Brokerから各Subscribersに座標を送信
1. 各Subscribersのキャンバスに描画

前述の通りPublisherは、自分の送信するデータメッセージを受信することができないので、自分のキャンバスに描画してからデータメッセージを送信する必要があります。
ホワイトボードのようにユーザ操作を遅延なくUIに反映させたいアプリケーションを作る場合はデータメッセージ送信前に自身のUIに反映させる方がユーザ体験上良いので、Publisherがデータメッセージを受信できる、できないにかかわらず同じような作りにはなるとは思いますが。
むしろ、Publisherは、自分の送信するデータメッセージを受信することができないので、Publisherで受信データを破棄しなくて良いので実装が楽かもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/aae632e4-b1eb-7802-977d-2b3908b61a50.png)


### 実装
#### サブスクライブ設定
realtimeSubscribeToReceiveDataMessageでsubscribeするtopicと対応するコールバック関数を登録するラッパ関数の例です。ここでは、データメッセージの受領時に、app.app.receivedDataMessageを呼び出すコールバック関数を定義して引数として使っています。なお、app.app.receivedDataMessage自体は別の場所で任意の処理を定義しておいてください。

```
export const setRealtimeSubscribeToReceiveDataMessage = (app:App, audioVideo:AudioVideoFacade, topic:string) =>{
    const receiveDataMessageHandler = (dataMessage: DataMessage): void => {
        app.receivedDataMessage(dataMessage)
    }
    audioVideo.realtimeSubscribeToReceiveDataMessage(topic, receiveDataMessageHandler)
}
```

#### データメッセージ送信
realtimeSendDataMessageを用いてデータメッセージを送る処理例です。
ホワイトボードに描画を行うために、始点と終点の座標、ストローク情報、線の太さなどをjosn化して送信しています。

```
    sendDrawsingBySignal = (targetId: string, mode:string, startXR:number, startYR:number, endXR:number, endYR:number, stroke:string, lineWidth:number)=>{
        const gs = this.props as GlobalState
        const message={
            action: 'sendmessage',
            data: JSON.stringify({ 
                cmd         : MessageType.Drawing,
                targetId    : targetId, 
                startTime   : Date.now(),
                mode        : mode,
                startXR     : startXR,
                startYR     : startYR,
                endXR       : endXR,
                endYR       : endYR,
                stroke      : stroke,
                lineWidth   : lineWidth
            })
        }
        gs.meetingSession?.audioVideo.realtimeSendDataMessage(MessageType.Drawing.toString(), JSON.stringify(message))
    }
```


### 動作デモ
#### ホワイトボード
作成したホワイトボード機能の動きはこのような感じになります。このデモは授業のホワイトボードを模擬したものとなります。右側で描画した内容が左側に反映されているのが分かるでしょうか？

![20200530170337.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/549fa1cc-4733-3b7f-b1d4-689db2102cc9.gif)


#### 画面共有上での描画
また、このホワイトボードをオーバレイの形で作ってあげると、Amazon Chime SDKの画面共有機能と併用しながらプレゼンをすることができます。
![20200530173726.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365991/2285d39d-3d96-705c-a6e1-bbbadd3b7d5f.gif)



### FLECT Amazon Chime Meeting
今回説明した機能は、現在FLECT研究開発室で、ビデオ会議を使った新機能のテストベッドに組み込まれています。
下記のリポジトリに公開していますので、ご興味を持たれましたらアクセスしてみてください。

https://github.com/FLECT-DEV-TEAM/FLECT_Amazon_Chime_Meeting


### 最後に
今回は、Amazon Chime SDKの最新機能を用いてホワイトボードを作成してみました。
日本では先日、緊急事態宣言の解除が発表されました。しかし、まだまだ教室に多くの人を集めて授業をするのは難しそうです。
また、同様に接客を行うにも、なかなかFace-to-Faceで接客というのもリスクがあり、難しいかもしれません。
ビデオ会議と共有ホワイトボードで、こういった課題に対応するというのも選択肢の一つではないかと思います。


次回は、またAmazon Chimeで遊ぶか、以前紹介したマルチバーコードリーダの技術的な内容をご紹介するかをしようと思ってます。
では。