agora.ioを利用したオンライン展示会(ブレークアウトルーム)のシステム開発

コロナの影響で展示会にオンライン化の流れが出てきています。
オンライン上で擬似的に展示会を体験できるツールとして[Remo](https://remo.co/conference/)が近しいかと思います。

今回、RemoのようなWebアプリをagora.ioで実装する方法を解説します。
サンプルコードは[こちら](https://github.com/fu-jimoto/AgoraIO-BreakoutRooms)にアップしています。
ブレークアウトルームのような利用方法も可能です。

##要件
オンライン展示会では基本的に以下の要件があります。
・会場入り
・メインステージからの映像と音声の受信
・ブースに入ってのクローズな商談
サンプルコードでは、ブースに入ってもメインステージからの映像音声は届く仕様になっています。
単純なパーテーションで防音効果のない現場を想定したものになります。

##画面イメージ
<img width="1255" alt="スクリーンショット 0002-07-03 11.43.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/e774ad20-1337-cf51-fdc6-c5399c100c16.png">
・APPIDはagora.ioのダッシュボードに[サインアップ](https://jp.vcube.com/service/agora/developer/tutorial/video/web.html)して取得します。
・Joinボタンクリックで会場入り
・MAIN STAGEクリックで会場内の人に映像と音声の送信開始
・room1 or room2クリックで個別のビデオ通話開始

##実装方法
実装ポイントは以下です。
・自映像のストリーム作成
・会場用のチャネルに接続
・会場に自映像の映像音声を配信
・ブース用のチャネルに接続
・他拠点の映像と音声を受信

###自映像のストリーム作成
自映像の作成は以下のAPIをコールします。

```javascript:
localStream = AgoraRTC.createStream({streamID: uid, audio: true, cameraId: camera, microphoneId: microphone, video: true, screen: false});
localStream.setVideoProfile('240p');//画質設定
localStream.init(function() {
  localStream.play('agora_local');//指定のDOMに映像表示
}, function (err) {
  console.log("getUserMedia failed", err);
});
```
<img width="1255" alt="step1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/957fe357-dc7d-8661-a68e-14e515cab119.png">
画面右端に自映像が固定で表示されます。今回のデモでは自映像が移動するようにはしていません。

###会場用のチャネルに接続
"main"というチャンネルが会場用になります。

```javascript
client = AgoraRTC.createClient({mode: 'live', codec:'vp8'});
client.init(appId.value, function () {
  console.log("AgoraRTC client initialized");
  client.join(channel_key, "main", null, function(uid) {
///中略
```

###会場に自映像の映像音声を配信
以下のAPIで会場に入室している人に自映像を配信します。

```javascript
client.publish(localStream, function (err) {
  console.log("Publish local stream error: " + err);
});
```

<img width="1255" alt="step2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/eb242b96-8040-7dbe-fc79-821200b4e872.png">


###ブース用のチャネルに接続
会場用とは別にブース用のクライアントを生成し、接続します。チャネルはroom1 or room2になります。
又、ブース内にいる人とビデオ通話をするので自映像を送信します。

```javascript
clientForRoom = AgoraRTC.createClient({mode: 'live', codec:'vp8'});
clientForRoom.init(appId.value, function () {
  console.log("AgoraRTC client initialized");
  clientForRoom.join(channel_key, room, null, function(uid) {
  clientForRoom.publish(localStream, function (err) {
    console.log("Publish local stream error: " + err);
  });
//中略
```
<img width="1255" alt="step3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/39973ae7-8e67-16e8-1d98-f265fb01e7b0.png">

##他拠点の映像と音声を受信
メインステージ、ブースそれぞれのクライアントに対して映像音声を受信できるようにします。
以下はメインステージ用のコードになります。

```javascript
  client.on('stream-added', function (evt) {
    var stream = evt.stream;
    console.log("New stream added: " + stream.getId());
    console.log("Subscribe ", stream);
    client.subscribe(stream, function (err) {
      console.log("Subscribe stream failed", err);
    });
  });

  client.on('stream-subscribed', function (evt) {
    var stream = evt.stream;
    console.log("Subscribe remote stream successfully: " + stream.getId());
    if ($('div#video #agora_remote'+stream.getId()).length === 0) {
      $('div#video').append('<div id="agora_remote'+stream.getId()+'" style="float:left; width:200px;height:150px;display:inline-block;"></div>');
    }
    stream.play('agora_remote' + stream.getId());
  });
```



##最後に
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=4d73ce9249d76f2cc5f6)
[<img width="912" alt="スクリーンショット 0001-08-15 13.41.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5d815376-9b89-08fa-9434-6fa7e8e67bcf.png">](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=4d73ce9249d76f2cc5f6)