コピペで最速で試すTwilioビデオ通話の実装 


Twilioのエルは一つ、今回のハッカソンで覚えたことです。 

> ![スクリーンショット 2021-06-07 13.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/eae75964-3896-6910-004d-fa3ee32ce789.png "スクリーンショット 2021-06-07 13.57.06.png")
> もはやどれが正解か分からないのがコンテンツ

ということでチェック事項が多いTwillllllioですが、APIトークンやシークレットキーなども複数あって中々概要掴むのが大変でした。

> [【勝手企画】Twilioオンラインコンテストに応募しちゃおうハッカソン](https://mashupawards.connpass.com/event/202313/)

## ビデオ映像のみのサンプルでまずは動かしたい

ハッカソン参加者が、モジュールのインストールなどでつまづいたりをみていると、ミニマムなサンプルがやはり欲しいなと思う今日この頃...... とりあえずコピペかつフロントエンドだけで試せる実装をしてみました。

> ![](https://i.gyazo.com/ac2c2a0d01436cf0e9c8facc8ae8e0e0.gif)

トークンをコードに直書きしてたりするので、 **この実装は実用性を考えるとオススメできないですが、まず動く、大枠を掴むって意味合いだと良いと思います。**

また、公式が推奨してるとかではないので悪しからず。

[Twilio WebRTCハンズオン（ホワイトボード編）](https://qiita.com/mobilebiz/items/c5f8d9e035871982b325)のコードから機能をバッサリ削除してます。

* マイク利用
* 発話検知
* ホワイトボード機能

などを排除して、カメラのみで1対1（2人）がアクセスしたときに映像を送りあえる部分だけの実装になります。なのでビデオ通話と書きましたが若干釣りですね。

## コピペで最速で試す

前提として、Twilioアカウントは取得しておいてください。

### 1. トークン取得

トークンも色々あって初見だと手強いんですよね。。という感じでこの手順だと試しやすいかなと思っています。

#### 1-1. サブアカウント作成

初めての場合はサブアカウント作成をします。

**Dashboard > 設定 > サブアカウント** でサブアカウントを作成します。

> 参考: [Twilio WebRTCハンズオン（ホワイトボード編）](https://qiita.com/mobilebiz/items/c5f8d9e035871982b325#%E3%82%B5%E3%83%96%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)

#### 1-2. 管理画面からアクセストークンを2つ発行

[テスティングツール](https://jp.twilio.com/console/video/project/testing-tools)でアクセストークンを発行できます。

**ここで2回アクセストークンを発行します。**

> ![スクリーンショット 2021-06-07 14.52.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/72b47051-2b44-e02f-8fd4-881dda7d9863.png "スクリーンショット 2021-06-07 14.52.53.png")

* クレデンシャルアイデンティティ: 適当な文字列
* Room名を選択する: 空

でOKです。

### 2. コピペコード（全文）

今回はVue.jsを利用しています。

PCの適当なフォルダにindex.htmlとscript.jsを作成しましょう。

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Camera Test</title>
    <style>
      #video-zone{
        display: flex;
        justify-content: space-around;
      }
      #video-zone video{
        width: 300px;
      }
    </style>
  </head>

  <body>
    <h1>Twilio WebRTCビデオ通話テスト (1対1 && Webカメラのみ)</h1>

    <div id="app">
      <div id="room-controls">
        <button id="button-join" @click="onclickA">Aさんとして入室</button>
        <button id="button-join" @click="onclickB">Bさんとして入室</button>
      </div>

      <div id="video-zone">
        <div id="my-video">
          <video id="myStream" autoplay playsinline></video>
        </div>
      </div>

    </div>

    <script src="https://media.twiliocdn.com/sdk/js/video/releases/2.7.3/twilio-video.min.js"></script>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="script.js"></script>
  </body>
</html>
```

先ほど発行したアクセストークン二つをtoken1とtoken2として設定します。

```script.js
//Vue v3
const app = Vue.createApp({
    data: () => ({
        ROOM_NAME: 'VideoRoom', // 部屋の名前
        Video: Twilio.Video, // Twilio Video JS SDK
        stream: {},
        // localStream: {},
        videoRoom: {},
        dataTrack: {},
        token1: 'トークン1',
        token2: 'トークン2',
    }),

    mounted: async function() {
        this.preview();
        this.dataTrack = new this.Video.LocalDataTrack();
    },

    methods: {
        //ビデオプレビュー
        preview: async function(){
            try {
                this.stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
                document.querySelector('#myStream').srcObject = this.stream;
                // this.localStream = this.stream;
            } catch (error) {
                console.log(error);   
            }
        },
        
        // 部屋に入室
        connectRoom: async function(token){
            try {
                const room = await this.Video.connect(token, {
                    name: this.ROOM_NAME,
                });

                console.log(`Connected to Room ${room.name}`);
                
                this.videoRoom = room;
  
                // すでに入室している参加者を表示
                room.participants.forEach(this.participantConnected);

                // 誰かが入室してきたときの処理
                room.on("participantConnected", this.participantConnected);
        
            } catch (error) {
                console.log(error);
            }
        },

        onclickA: function(){ console.log('A Click--'); this.connectRoom(this.token1)}, //Aとしてルームに接続
        onclickB: function(){ console.log('B Click--'); this.connectRoom(this.token2)}, //Bとしてルームに接続

        //他の参加者が入室した処理
        participantConnected: function(participant){
            console.log(`connect!`);
            console.log(`Participant ${participant.identity} connected'`);
        
            // 参加者を表示する
            const div = document.createElement("div");
            div.id = participant.sid;
            div.classList.add("remote-video");
                
            // 参加者のトラックが届いたとき
            participant.on('trackSubscribed', (track) => this.trackSubscribed(div, track));
                
            // 参加者の画像を表示
            const videoZone = document.getElementById('video-zone');
            videoZone.appendChild(div);
        },

        //サブスクライブ
        trackSubscribed: function(div, track){
            const child = div.appendChild(track.attach());
            if (track.kind === "video") {
                child.classList.add("video-style");
            }
        },

    },

});
app.mount('#app');
```

まだ余計なコード残ってるかもしれないですが一旦こんな感じにまとめてみました。

### 3. 起動

[VSCodeのライブサーバー](https://life-care.site/programming/liveserver_install_how_to_use)や[serve](https://www.npmjs.com/package/serve)などでローカルサーバーを起動させましょう。

僕はserveをnpx起動するのが最近は多いです。

```bash
$ npx serve -p 3000
```

### 4. 試し方

`http://localhost:3000`にアクセスすれば表示されます。

二つのタブでページを開き、片方でAさん、もう片方はBさんで入室しましょう。

> ![](https://i.gyazo.com/b737f25fc1388359c56c37928ece22c8.gif)

## トークンは1時間しか使えないので注意

Twilioは動的にアクセストークンを発行していて1時間に一回更新されるとのことです、1時間以内ならこのトークンで試すことが出来ますが、それ以上使っていく場合は大元のハンズオン資料をもとに実装していきましょう。

このコードに追加する場合はボタンクリックした際にアクセストークンを生成するサーバー（を作成しておいて）にアクセスしてトークン取得すると良さそうです。

また、今回二つのアクセストークンを作成しましたが、アクセストークン一つで良いのでは？と思う人もいそうです。

> 通常、動的にトークンを払い出す場合は、アイデンティティは同じでも、時間を加味して別のトークンが払い出されるので、同じユーザでも別のトークンになりますけど、今回は全く同じトークンですからね。

と赤い芸人さんからコメント頂きました。ありがとうございます。

同じアクセストークン同士だとうまく動いてくれない模様ですね。

## まとめ

こんな感じでNode.jsなども利用せずにフロントだけでTwilioのWebRTC機能を試すことが出来ました。

分解して再構築してみると理解深まりますね！色々と排除したのでホワイトボード側のデータやり取りについてはちゃんと追えてないですが苦笑

また、1時間でトークンは切れるみたいですが、使い終わったらトークンを削除しておくのが良いと思います。