Agoraでweb会議システムを作ってみよう！

# はじめに
最近何かとよく目にするClubhouse。そのClubhouseで使われているっぽいAgoraを今回使用し、web会議システム的なものを作ってみようという記事です。

# Agoraとは
* Agoraは、ネイティブアプリやWebサイトにビデオ通話やライブ配信をかんたんに実装できるSDKです。

## 特徴
* [WebRTCと互換性があり、P2P通信よりも安定しています。](https://jp.vcube.com/service/agora)と書いてあるように、Agoraは、WebRTC互換の技術を使用しており、通信はP2PではなくAgoraのサーバを使うそうです。
ただ、他のビデオ通話系のサービスである、ZoomやGoogle Meetなども全てサーバ経由なので、他のサービスと方式は同じようですね。
* プライベートネットワークでサーバ間を繋ぐのが強みのサービスのようです。
* 1000 人以上の配信(双方向通話)が可能のようです。(片方向のpush型ならより多くなるのではないか？)
* 従量課金制だが、音声10,000 分/月の無料枠があるようで、クレジットカードの登録なしで利用できるようです。

# やってみよう
## アカウント作成
① まず、 https://www.agora.io/en/ にアクセスし、右上の「Get Started」をクリックしてください。
![スクリーンショット 2021-02-04 9.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/48957a22-af29-581d-ea54-7578766186eb.png)

② SMS認証があるので、必須項目を入力していく。
![スクリーンショット 2021-02-04 9.43.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/315e76c2-3a25-b32f-280d-d04f305f98f1.png)

③ コンソール画面に入ってみる。
![スクリーンショット 2021-02-04 9.58.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/02e71548-5eaf-6e5a-1ca3-28209dbe0d27.png)


## プロジェクトの作成
① 「new project」をクリックする
![スクリーンショット 2021-02-04 9.58.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/4f7ec269-8b2e-84d3-6272-36f03286d21b.png)

② プロジェクトの名前を入力し、「Authentication Mechanism」を「Secured mode」を選択
![スクリーンショット 2021-02-04 12.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/ece10dde-7348-6c83-5ae3-0b755c26cc5a.png)


④ Project Managementから、作成したプロジェクトがあるか確認する
![スクリーンショット 2021-02-04 12.34.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/8c7c8c8d-5fff-48a3-234e-70894911e0f1.png)

⑤ で確認したプロジェクトの右側にある「edit」を選択する。
![スクリーンショット 2021-02-04 12.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/ac42c05a-0489-dc7a-dcff-58a2ac473fe6.png)


⑥ App IDとApp Certificate(Primary Certificate)の項目の右側の目のところをクリックし、コピーする
=> これが認証情報になります。
![スクリーンショット 2021-02-04 12.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/b1a529e8-ac87-5d2a-c1e4-9a48319f0829.png)

## 実装
* 今回はvueを用いて、クライアント側の実装をしていこうと思います。
事前にvue cliは入れていただければと思います。
① vue cliを入れていれば下記のコマンドvueのプロジェクトを作成できます。

```
vue create agora-poc
```

② npmを利用し、agora SDKをinstallします。

```
npm install agora-rtc-sdk
```

③ vue.config.jsファイルを作成し、下記のものをコピペする

portはなんでも良いのですが、[hostは127.0.0.1でなければなりません。](https://docs.agora.io/en/Video/start_call_web?platform=Web)

```vue.config.js
module.exports = {
    devServer: {
        host: '127.0.0.1',
        port: 9999,
        disableHostCheck: true,
    },
};
```

④ 下記のものをHelloWorld.vueに貼り付ける
vueで動作させるために結構このコード頑張りました。w
また、ソースコードが汚いのは勘弁してください。。
（ちょろっと体験したかったため、リファクタを全くしていません。w）

```HelloWorld.vue
<template>
  <div class="hello">
    <h1>
      Video Call<br><small style="font-size: 14pt;">Powered by Agora.io</small>
    </h1>
    <h4>Local video</h4>
    <div id="me"></div>
    <h4>Remote video</h4>
    <div id="container"></div>
  </div>
</template>

<script>
import AgoraRTC from 'agora-rtc-sdk'
export default {
  name: 'Helloworld',

  created() {
    let client = AgoraRTC.createClient({
      mode: "rtc",
      codec: "vp8",
    });

    let localStream = AgoraRTC.createStream({
      audio: true,
      video: true,
    });

    client.init("yourAppId");

    client.join("yourToken", "test", null, ()=>{
      localStream.init(()=>{
      localStream.play("me");
      client.publish(localStream, handleError);
      }, handleError);
      client.on("stream-added", function(evt){
        client.subscribe(evt.stream, handleError);
      });
      client.on("stream-subscribed", function(evt){
        let stream = evt.stream;
        let streamId = String(stream.getId());
        addVideoStream(streamId);
        stream.play(streamId);
      });
      client.on("stream-removed", function(evt){
        let stream = evt.stream;
        let streamId = String(stream.getId());
        stream.close();
        removeVideoStream(streamId);
      });
      client.on("peer-leave", function(evt){
        let stream = evt.stream;
        let streamId = String(stream.getId());
        stream.close();
        removeVideoStream(streamId);
      });
    }, handleError);
  }
}

const handleError = function(err){
  console.log("Error: ", err);
};

function addVideoStream(elementId){
  let streamDiv = document.createElement("div");
  streamDiv.id = elementId;
  streamDiv.style.transform = "rotateY(180deg)";
  streamDiv.style.width = "400px";
  streamDiv.style.height = "400px";

  document.getElementById("container").appendChild(streamDiv);
}

function removeVideoStream(elementId) {
  let remoteDiv = document.getElementById(elementId);
  if (remoteDiv) remoteDiv.parentNode.removeChild(remoteDiv);
}
</script>

<style scoped>
* {
  font-family: sans-serif;
}
h1,h4 {
  text-align: center;
}
#me {
  width: 400px;
  height: 400px;
  margin: 0 auto;
}
#me video {
  position: relative !important;
}
#container video {
  position: relative !important;
}

</style>

```

注意点1: 上記コードの下記の箇所には、手順の中でメモをしたAppIdを入れます。

```
client.init("yourAppId");
```

注意点2: 上記のコードの下記の箇所にはtokenを入れます。

```
client.join("yourToken", "test", null, ()=>{
```

tokenの発行は、プロジェクトのeditから下記の箇所を選択すると取得する画面に移動します。
![スクリーンショット 2021-02-04 23.17.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/875ac9d7-a853-8aff-f105-205957164b5a.png)

## 動作させてみよう！
tuxくんに出てきてもらいましょう！ ちなみに画像の画質が悪いのは、かなり圧縮している為です。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/94c2e623-b146-465d-2298-e5a0cd6c9d19.gif)










# おわりに
ビデオ通話系だと他にZoomのSDKとかあったりすると思うので、そのうちそちらもやってみたいと思います。

# 参考
https://docs.agora.io/en/Voice/landing-page?platform=Web
https://zenn.dev/arahabica/articles/0f54f2cdb1a29d
https://zenn.dev/voluntas/scraps/9403b803320d6f
https://zenn.dev/ginpei/articles/agora-voice-chat