Vonage Video APIを爆速で始める

## Vonageとは

そもそもVonageを知らない人が結構多いだろうということで、まずはVonageが何かというところから。

Vonageとは **CPaas (Communication Platform as a Service)** の一種で、コミュニケーションに必要となるような技術（ビデオ通話、音声通話、SMS）などをサービスとして利用できるものです。自前で実装するよりラクチンだね！

具体的には以下のような機能を提供しています

> - Video API デベロッパーセンター
>   - Vonage Video API：WebRTCプラットフォーム（APIとSDK）
>   - Vonage Video API Tools：Vonageが提供している開発・デバッグツール
> - Vonage デベロッパーセンター
>   - Vonage Verify API：二要素認証API
>   - Vonage Voice API：PSTN・SIP・Websocket対応できるプログラマブルボイスAPI
>   - Vonage In-App SDK：アプリ上のメッセージ・音声（PSTN・SIP・Websocketも対応）SDK
>   - Vonage SMS API：SMSの送受信API
>   - Vonage Messaging API：Facebook Messenger、WhatsApp、Viber等の送受信API
>   - Vonage Management API：上記APIの利用レポート・アカウント管理・電話番号管理API

([Vonageのアドカレページ](https://qiita.com/advent-calendar/2022/vonage)から引用)

歴史的な経緯からVideo APIとVideo API以外の開発者ポータルが分かれてますが、今回はVideo APIの方に焦点を当てて行こうと思います。

## 始める

### アカウント登録

まずはVonageのアカウント登録から始めます。

まずは[Vonageのアドベントカレンダーのページ](https://qiita.com/advent-calendar/2022/vonage)から「Video API (tokbox) アカウントの作成」を探してアカウント登録のページに行きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/94fdfa5f-5cfa-f709-7a6d-f44c0e56a186.png)

必要事項を入力して「Redeem your $10 credit」をクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/415d1562-f48b-38ed-296d-4ea4cab0ffe7.png)

次の画面でも必要事項を入力して（任意）「Next」をクリック。

最後にメールアドレスを認証してアカウント登録は完了です。

### Video APIを使う

アカウント登録が済んだらログインして、ダッシュボードに行きます。

するとおそらく以下のようなプロジェクト作成画面が出てくると思います。（出てこなかったら左にある「Create Project」をクリックしてください）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/b6dedbce-ea2f-31d0-ecfe-9fdf9a9ff0cd.png)

とりあえず導入が超簡単な「Video Chat Embed」の方を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/e54208d0-8bcc-a472-0d5a-87fa8c41c63b.png)

名前を適当に決めて、URLは`http://localhost:5500`を入力（`5500`はポート番号で、適宜変更してください）

「Next」を押したらコードが表示されると思うので、これをコピーしてそのままHTMLファイルとして保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/7046baec-5a78-d08d-8720-e54a71bcd0ec.png)

それをLive Serverなりでホストしてみると...？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/7a1be796-c9e0-809a-ed55-bb868914f206.png)

！？！？！？！？！？！？！？！？！？

なんとこれだけでVonage Video APIを使いはじめることができて、「Click to Start Video Chat」をクリックするだけでビデオ通話が始められます！！

:::note warn
ブラウザがカメラやマイクを利用するときは、接続先がhttpsか`localhost`である必要があるので注意！！
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/f79a092d-fb06-f0f8-71ab-c9ce5d1eaffc.png)

⇧⇧⇧同じパソコンで4タブ開いて参加してみた様子（カメラ映像見せたくないので手元にあったイラストで誤魔化してますが）

UIなどをいじれないという欠点はありますが「Video Chat Embed」を使うと **一瞬で** プロジェクトにビデオ通話を導入できます。

### より高度に使う

プロジェクトの作成画面で、もう一方の「Vonage Video API」の方を選択すると、自分でAPIを利用してカスタマイズできるビデオ通話を実現できます。

[公式のチュートリアル](https://tokbox.com/developer/tutorials/web/basic-video-chat/)に従って進めていきます。

まずはプロジェクトをさっきと同じような手順で作成し、その時に出てきた「API Key」と「API Secret」をメモっておきます。

次にプロジェクトの概要のページから「Create Session ID」を押してセッションIDを生成して、出てきた値をメモっておきます。

その下のGenerate Tokenのところから「Session ID」にさっきの値を入れて、「Generate Token」をクリックして、出てきた値をメモっておきます。

そしたら`index.html`、`js/app.js`、`css/app.css`を以下のような内容で作成します。`app.js`の中の`YOUR_API_KEY`、`YOUR_SESSION_ID`、`YOUR_TOKEN`はさっきメモった値に置き換えてください。

```html:index.html
<html>
  <head>
    <title>Vonage Video APIテスト</title>
    <link href="css/app.css" rel="stylesheet" type="text/css" />
    <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
  </head>
  <body>
    <div id="videos">
      <div id="subscriber"></div>
      <div id="publisher"></div>
    </div>

    <script type="text/javascript" src="js/app.js"></script>
  </body>
</html>
```

```js:app.js
// メモした値を入力する
const apiKey = 'YOUR_API_KEY';
const sessionId = 'YOUR_SESSION_ID';
const token = 'YOUR_TOKEN';

initializeSession();

// エラーはalertで通知する
function handleError(error) {
  if (error) {
    alert(error.message);
  }
}

function initializeSession() {
  const session = OT.initSession(apiKey, sessionId);

  // 新しく作られたstreamにsubscribeする
  session.on('streamCreated', function (event) {
    session.subscribe(
      event.stream,
      'subscriber',
      {
        insertMode: 'append',
        width: '100%',
        height: '100%',
      },
      handleError
    );
  });

  // publisherを作成
  const publisher = OT.initPublisher(
    'publisher',
    {
      insertMode: 'append',
      width: '100%',
      height: '100%',
    },
    handleError
  );

  // セッションに接続
  session.connect(token, function (error) {
    // 接続に成功したら、セッションにpublishする
    if (error) {
      handleError(error);
    } else {
      session.publish(publisher, handleError);
    }
  });
}
```

```css:app.css
body, html {
  background-color: gray;
  height: 100%;
}

#videos {
  position: relative;
  width: 100%;
  height: 100%;
  margin-left: auto;
  margin-right: auto;
}

#subscriber {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
}

#publisher {
  position: absolute;
  width: 360px;
  height: 240px;
  bottom: 10px;
  left: 10px;
  z-index: 100;
  border: 3px solid white;
  border-radius: 3px;
}
```

そしてLive Serverなどで適当に`index.html`をホストしてあげると...？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/8e22a41e-26d3-809e-913f-0940c64cb44f.png)

無事ビデオ通話をすることができました！！🎉🎉

さっきの埋め込み式に比べてボタンなどが少なかったりしますが、自分で拡張していくことが出来るので、凝ったUIを作りたいという人はこっちの方が向いてるかもしれません。

## さいごに

プレゼントにつられてホイホイ記事を書いたんですが、思ったより使い始めるのが簡単でビビりました。特に埋め込みだけでできるとかエグすぎ...

余談ですが、チュートリアルはHTMLファイルを使うようなレガシーな感じだったんですが、モダンに行きたいなーということで[Deno](https://deno.land/)+[Fresh](https://fresh.deno.dev/)という構成で行こうかと思ったら謎のエラーが解決せずにやめました。まだDenoはnpmを完全にサポートしてるというわけでもなさそう。

コメント・指摘など歓迎