Sora JavaScript SDKを使ってみた


## はじめに

時雨堂さんのSoraを使ったライブ配信を試しました。
（ウソ穴という個人開発のシステムで使えるか試してみたかった→動いた！）

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">A-Frame と 時雨堂さんの sora を使うとスマホで <a href="https://twitter.com/hashtag/%E3%82%A6%E3%82%BD%E7%A9%B4?src=hash&amp;ref_src=twsrc%5Etfw">#ウソ穴</a> つくれた。わかりにくいですが、映像をリアルタイムに3Dオブジェクトにマッピングしてて <a href="https://twitter.com/hashtag/AR?src=hash&amp;ref_src=twsrc%5Etfw">#AR</a> で表示しています。 <a href="https://t.co/HSvkgSoHQ3">pic.twitter.com/HSvkgSoHQ3</a></p>&mdash; j4amountain (@zsipparu) <a href="https://twitter.com/zsipparu/status/1227206840527646720?ref_src=twsrc%5Etfw">February 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

今回は、ライブ配信するところまでを紹介します。

## 参考サイト

こちらのサイトを参考にさせて頂きました。

- [Sora JavaScript SDK ドキュメント](https://sora-js-sdk.shiguredo.jp/index.html)
- [Sora LaboでSora JavaScript SDKを試す](https://qiita.com/tetsu_koba/items/d66d4306890aa5820158)

## 環境

- Webサーバー
    - Windows10 / Nodejs v12.13.1 (オレオレ証明書あり)
- 映像配信の端末
    - Windows10
    - iOS 13.3.1
- 映像受信の端末
    - Windows10

## 作りかた

では、作っていきます。

#### 1.Sora Laboにログイン

サイト（[https://sora-labo.shiguredo.jp/](https://sora-labo.shiguredo.jp/)）にアクセスしアカウントを登録し、以下3つの情報を取得します。

- シグナリング URL(wss://ではじまるもの) 
- シグナリングキー(signaling_key)
- channelId　※ {{github-id}}@sora-labo

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/927bc721-9910-76ae-b1fe-2d1267f92f9c.png" width="350">


#### 2.sora.min.jsを取得

git bash で取得します

```console
$ curl -OL https://raw.githubusercontent.com/shiguredo/sora-js-sdk/master/dist/sora.min.js
```

#### 3.配信/受信サイトを用意

[こちらのサイト](https://sora-js-sdk.shiguredo.jp/quickstart.html)から`upstream.html`と`downstream.html`を取得する。channelIdとsignaling_keyを自分のものに修正します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/568bd50c-ef1f-2dbc-7eb0-1f62e387eb18.png)

```html:upstream.html
<html lang="ja">
    <head>
    <meta charset="utf-8">
    </head>
    <body>
    <video id="local-video" autoplay controls muted></video>
    <script type="text/javascript" src="./js/sora.min.js"></script>
    <script type="text/javascript">
     const channelId = 'xxxxxxxxx@sora-labo';
     const signalingUrl = 'wss://xxxxxxxxxxxxxxxx';
     const metadata = {"signaling_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};

     const debug = true;
     const sora = Sora.connection(signalingUrl, debug);
     let options = {
             audio: true,
             audioCodecType: 'OPUS',
             audioBitRate: 96,
             video: true,
             videoCodecType: 'H264',
             videoBitRate: 1500,
         }
     const publisher = sora.publisher(channelId, metadata, options);
     let constraints = {
             audio: true,
             video: {
                 width: 640,
                 height: 480,
                 frameRate: 20,
             }
         }
     navigator.mediaDevices.getUserMedia(constraints)
          .then(stream => publisher.connect(stream))
          .then(stream => {
              document.querySelector('#local-video').srcObject = stream;
          })
          .catch(e => { console.error(e); })
    </script>
    </body>
</html>
```

```html:downstream.html
<head>
    <meta charset="utf-8">
</head>
<body>
    <video id="remote-video" autoplay controls muted></video>
    <script type="text/javascript" src="./js/sora.min.js"></script>
    <script type="text/javascript">
     const channelId = 'xxxxxxxxx@sora-labo';
     const signalingUrl = 'wss://xxxxxxxxxxxxxxxx';
     const metadata = {"signaling_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};

     const debug = true;
     const sora = Sora.connection(signalingUrl, debug);
     let options = {
         audio: true,
         audioCodecType: 'OPUS',
         audioBitRate: 96,
         video: true,
         videoCodecType: 'H264',
         videoBitRate: 1500,
     }
     const subscriber = sora.subscriber(channelId, metadata, options);

     subscriber.connect()
               .then(stream => {
                   document.querySelector('#remote-video').srcObject = stream;
               })
               .catch(e => {
                   console.error(e);
               });
    </script>
</body>
</html>
```

ファイル構成

```cosole
$ tree
.
├── downstream.html
├── upstream.html
└── js
    └── sora.min.js
```



- 配信サイト
    - 例: `https://{{WebサーバーのIPアドレス}}:{{ポート番号}}/upstream.html`
- 受信サイト
    - 例: `https://{{WebサーバーのIPアドレス}}:{{ポート番号}}/downstream.html`

これで完成です。

#### 動作確認

- 配信端末で、配信サイト`https://{{WebサーバーのIPアドレス}}:{{ポート番号}}/upstream.html`を開く
- 受信端末で受信サイト`https://{{WebサーバーのIPアドレス}}:{{ポート番号}}/downstream.html`を開く

配信端末のカメラ映像を受信端末で表示できたら成功です。
配信端末がiPhoneの場合は、配信開始ボタンをタップすると配信が開始されます。