【SkyWay】WebRTC初心者がビデオ通話を作ってみたらそれっぽいものができた

## SkyWayが新しくなったよ
そもそもWebRTCとはWebブラウザ間で音声やビデオ、データなどをリアルタイムにやり取りする際に用いられる技術のことです
そしてSkyWayが提供しているWebRTC用のSDKがリニューアルしたみたいです！

今回は公式チュートリアルを参考に**ビデオ通話WEBアプリを作ってみました**🙆‍♂
~~最近新しくなったばかりでドキュメントがあまり無かったため苦労しました、、~~
~~(最終的にSDKのソースコードを読んでました)~~
↓記事を投稿してからめっちゃいいドキュメントがあることを知りました、、
https://javascript-sdk.api-reference.skyway.ntt.com

**簡単にサンプルを作れるようにまとめた**ので~~踏み台~~参考にしてくれたらうれしいです

公式ドキュメントはこちら↓
https://skyway.ntt.com/ja/docs/user-guide/javascript-sdk/quickstart/

## 先に作ったものを紹介
room nameに部屋名を入力してチャットに参加できるよ
左側が自分の画面で右が通話相手の画面だよ(実物は音声もあります)
**何かそれっぽい！**
![9-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124426/313f2733-92d9-e309-dfec-f4dbea317cd9.gif)

## さっそく作り方
### 1. SkyWay側の準備
まずは[ここから](https://console.skyway.ntt.com/login)アカウントを作りましょう
アカウントができたらプロジェクトを作成してアプリケーションを作成したら準備OKです
![9-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124426/e61a76f0-c969-865a-5ca4-1acdc1bd53fb.png)


### 2. ソースコード
ファイルは2つだけです
<details><summary>index.html</summary>

```html:index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width" />
        <title>SkyWay Tutorial</title>
    </head>
    <body>
        <p>ID: <span id="my-id"></span></p>
        <div>
            room name: <input id="room-name" type="text" />
            <button id="join">join</button>
        </div>
        <div style="display: flex;">
            <video id="local-video" width="400px" muted playsinline></video>
            <div id="remote-media-area"></div>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/@skyway-sdk/room/dist/skyway_room-latest.js"></script>
        <script src="main.js"></script>
    </body>
</html>
```
</details>

<details><summary>main.js</summary>

```javascript:main.js
const { nowInSec, SkyWayAuthToken, SkyWayContext, SkyWayRoom, SkyWayStreamFactory, uuidV4 } = skyway_room;


// SkyWay Auth Tokenの作成(JWT形式)
// 本当はサーバー側で作成する
const token = new SkyWayAuthToken({
    jti: uuidV4(),
    iat: nowInSec(),
    exp: nowInSec() + 60 * 60 * 24,
    scope: {
        app: {
            id: 'アプリケーションID',
            turn: true,
            actions: ['read'],
            channels: [{
                id: '*',
                name: '*',
                actions: ['write'],
                members: [{
                    id: '*',
                    name: '*',
                    actions: ['write'],
                    publication: {actions: ['write'],},
                    subscription: {actions: ['write'],},
                },],
                sfuBots: [{
                    actions: ['write'],
                    forwardings: [{actions: ['write'],},],
                },],
            },],
        },
    },
}).encode('シークレットキー');

(async () => {
    const localVideo = document.getElementById('local-video');
    const remoteMediaArea = document.getElementById('remote-media-area');
    const roomNameInput = document.getElementById('room-name');
    const myId = document.getElementById('my-id');
    const joinButton = document.getElementById('join');

    // カメラ映像、音声の取得
    // カメラ、マイクのデバイスが無い、許可をしないとエラーとなるので注意！
    const { audio, video } = await SkyWayStreamFactory.createMicrophoneAudioAndCameraStream();
    localVideo.muted = true;
    localVideo.playsInline = true;
    video.attach(localVideo);
    // 映像の再生
    await localVideo.play();

    joinButton.onclick = async () => {
        if (roomNameInput.value === '') return;

        const context = await SkyWayContext.Create(token);
        // 同じ名前の部屋(room)が存在しなければ作成し、存在する場合にはそのroomを取得する
        const room = await SkyWayRoom.FindOrCreate(context, {
            type: 'p2p',
            name: roomNameInput.value,
        });

        // roomに入室
        const me = await room.join();
        myId.textContent = me.id;

        // 自分の映像、音声の公開(publish)
        await me.publish(audio);
        await me.publish(video);

        // Room上でStreamがSubscribeされた時に発火
        me.onPublicationSubscribed.add(async ({ stream, subscription }) => {
            const userVideo = {};
            const publisherId = subscription.publication.publisher.id;
            if (publisherId === me.id) return;
            if (!userVideo[publisherId]) {
                const newVideo = document.createElement('video');
                newVideo.playsInline = true;
                newVideo.autoplay = true;
                newVideo.setAttribute( 'data-member-id', publisherId )
                remoteMediaArea.append(newVideo);
                userVideo[publisherId] = newVideo;
            };
            const newVideo = userVideo[publisherId];
            stream.attach(newVideo);
        });

        const subscribe = async (publication) => {
            if (publication.publisher.id === me.id) return;
            await me.subscribe(publication.id);
        };

        // RoomにStreamがPublishされたときに発火
        room.onStreamPublished.add((e) => subscribe(e.publication));
        room.publications.forEach(subscribe);
    };
})();
```
</details>

### 3. 試そう
ファイルをコピーしたらVSCodeで開きましょう
index.htmlをLive Serverで開くとブラウザが勝手に立ち上がりページが表示されます
そして別タブでもう一個開いて適当な部屋名を入れれば通話ができるよ
**カメラとマイクが無いとエラーが出ちゃうので、無かったら仮想デバイスを入れてね**

PCとスマホで試したい場合はChromeのinspectとport forwardingを使えばUSBデバッグが有効になっているAndroid端末でlocalhostでサイトを表示できるようになります

## 最後に
WebRTCなんて用語も知りませんでしたが思ったよりいい感じに作れました
いいね、ストック宜しくお願いします🔥