オンライングループレッスン＋サブ講師のモニタリング

オンラインでの各種レッスン（ヨガやフィットネス等）が流行しています。
この記事ではグループレッスンをしつつ、サブ講師が生徒の様子をモニタリングできるシステムのサンプルを公開したので解説をします。
Agora.io WebSDKのサンプルをベースにカスタマイズしています。

[サンプルコードはこちら](https://github.com/fu-jimoto/AgoraIO-LessonMonitor)

##基本仕様
- N人毎にチャネルが別れる (グループチャンネルA,B,C...)
- 講師はライブ配信のみ
- サブ講師は初期で視聴のみでAチャネルに入る
- サブ講師はChangeをクリックでBチャネルに入る
- サブ講師は講師と同じ場所にいると仮定し、講師の映像は受け取らない
- 生徒はライブのチャネルにおいて映像を常に受け取る
- 生徒は個別チャネルにおいて映像を送るが他拠点の映像は受信しない

##画面イメージ
###講師
![Basic_Video_Call_--_Agora.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/92fcfd23-2fca-4836-7060-a5423a22d4ea.png)
講師は自映像のみが映っています。

###生徒
![Basic_Video_Call_--_Agora_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/96cca646-39f0-73fe-15f7-1c58bf30db50.png)
生徒は講師の映像と自分の映像が映っています。他の生徒の映像は受信していません。

###サブ講師
![sub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/1b858fb0-1894-e69b-e3d8-9823759e08ea.png)
サブ講師は生徒の映像のみが映っています。

##実装の内容

###講師
```host.js
async function join() {

  // add event listener to play remote tracks when remote user publishs.
  client.on("user-published", handleUserPublished);　
  client.on("user-unpublished", handleUserUnpublished);

  // join a channel and create local tracks, we can use Promise.all to run them concurrently
  [ options.uid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([
    // join the channel
    client.join(options.appid, options.channel, options.token || null,1000),
    // create local tracks, using microphone and camera
    AgoraRTC.createMicrophoneAudioTrack(),
    AgoraRTC.createCameraVideoTrack()
  ]);
  
  // play local video track
  localTracks.videoTrack.play("local-player");
  $("#local-player-name").text(`localVideo(${options.uid})`);

  // publish local tracks to channel
  await client.publish(Object.values(localTracks));
  console.log("publish success");
}

```
mainチャンネルに接続＆映像の配信処理をしています。

###生徒
```student.js
async function join() {

  // add event listener to play remote tracks when remote user publishs.
  client.on("user-published", handleUserPublished);//講師映像は受信
  client.on("user-unpublished", handleUserUnpublished);

  // join a channel and create local tracks, we can use Promise.all to run them concurrently
  [ options.uid ] = await Promise.all([
    // join the channel
    client.join(options.appid, options.channel, options.token || null),
  ]);
  
  var channelName = getChannelName();
  // join a channel and create local tracks, we can use Promise.all to run them concurrently
  [ options.subUid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([
    // join the channel
    subClient.join(options.appid, channelName, options.token || null),
    // create local tracks, using microphone and camera
    AgoraRTC.createMicrophoneAudioTrack(),
    AgoraRTC.createCameraVideoTrack()
  ]);

  // play local video track
  localTracks.videoTrack.play("local-player");
  $("#local-player-name").text(`localVideo(${options.uid})`);

  // publish local tracks to channel
  await subClient.publish(Object.values(localTracks));//サブ講師に向けて映像送信
  console.log("publish success");
}

```

講師映像を受け取るチャンネルとグループのチャンネルそれぞれに入室しています。グループのチャンネルには映像を配信しています。
又、mainチャンネルの映像は受信する処理がありますが、グループのチャンネルは受信する処理がないので他拠点の生徒映像は映りません。（受信する実装を追加すれば映して会話しながらレッスンということも可能です）


###サブ講師
```sub.js
async function join() {

  // add event listener to play remote tracks when remote user publishs.
  client.on("user-published", handleUserPublished);
  client.on("user-unpublished", handleUserUnpublished);
    
  // add event listener to play remote tracks when remote user publishs.
  if(options.channel=="A"){
    options.channel="B";
  }else{
    options.channel="A";
  }
  // join a channel and create local tracks, we can use Promise.all to run them concurrently
  [ options.uid ] = await Promise.all([
    // join the channel
    client.join(options.appid, options.channel, options.token || null),
  ]);

}
```
グループのチャンネルを切り替える処理が入っています。（Aチャンネルにいる時はBチャンネルへ移動)



# 最後に
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=c6275792146d78d4423)
[<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=c6275792146d78d4423)