Amazon Interactive Video Serviceのストリームチャット機能をためしてみた

2022.04.29

いわさです。

Amazon Interactive Video Service(IVS)はフルマネージドなライブストリーミングサービスです。

先日、こちらにストリームチャット機能が追加されたので試してみました。

Amazon IVS Chat API

Amazon IVSのストリームチャット機能と聞いて最初よくわからなかったのですが、こちらどうやらAmazon IVSという名前がついてはいるのですが、実態は全く別のAPIとして提供されているようで、メディアのライブストリーミングとは直接関係なさそうです。

何が出来るかざっくり言うと、AWS側は以下を担当してくれます。

  • WebSocketサーバーのホスティング
  • サーバー接続用の認証トークンの払い出しと管理

従来のビデオストリーミングとの統合や、クライアントアプリケーションの実装などは全てユーザーの責務です。
トークン発行はAPI/SDKが提供されていますが、チャット通信部分は汎用的なWebSocketのクライアント実装が必要です。

本日時点では3リージョン(バージニア北部、オレゴン、アイルランド)でのみ利用が可能です。
アップデート情報では他の地域でもすぐ利用可能になるぜと書いてあったので期待して待ちましょう。

価格

Amazon Interactive Video Service Pricing

気になる価格ですが、ルームのプロビジョニング時間などに応じた料金は発生しません。
送信されたメッセージに応じた以下の料金体系となっています。(2022/4/28時点)

  • 送信されたメッセージ1,000通あたり: $0.56
  • 配信されたメッセージ1,000通あたり: $0.008

配信メッセージ数の考え方ですが、仮に1,000人のユーザーがチャットルームに接続しているときに2つのメッセージを送信すると、2,000件のメッセージが配信されることになります。
ユーザー数に応じて配信数が増えるので試算の際にはご注意ください。

また、チャット機能はビデオのライブストリーミングと機能的には分離されているのですが価格面では少し関係があります。
ビデオ入力の1時間ごとに、2,700の送信メッセージと270,000の配信メッセージを無料で利用出来るようになります。
単独でチャット機能を使うことも出来ますが、ビデオライブストリーミングと併用することで料金面での優遇がある点を覚えておきましょう。

ためしてみた

いくつかオプション機能があったりもするのですが、本日は最低限の機能でチャットを行えるようにするところまでを実現したいと思います。

ルーム作成&トークン発行

対象リージョンで「Amazon IVS チャットルーム」が開始出来るようになっています。

まずは「ルーム」を作成します。
ルームごとにエンドポイントが作成されるわけではないのですが、チャットトークンはルームにひも付きます。

ルームの設定として以下がカスタマイズ可能です。デフォルト設定は最大値になっているので制限を強めたいわけでなければデフォルト設定で良さそうです。

  • メッセージの最大文字数: 1メッセージあたり500文字, デフォルト500
  • 最大メッセージレート: 1秒あたり10メッセージ, デフォルト10

メッセージレビューハンドラーは今回は無効にしますが、これはちょっとおもしろいですね。
メッセージを無条件で配信させるのではなく、メッセージをレビューし、許可・拒否・変更を行うことが出来ます。ハンドラーを設定しLambda関数を実行してその中で制御を行うことが出来ます。
すぐに思いつくところだとNGワードを伏せ字にしたりブロックしたり、とかでしょうか。
今度試してみますが今日は無効にしますね。

チャットトークンはSDKやCLIでも作成出来ます。
詳細は以下をご確認ください。

Step 3: Authenticate and Authorize Chat Clients - Amazon Interactive Video Service

開発向けですが、マネジメントコンソール上からもチャットトークンが作成出来ますので本日はこちらを利用してみます。

オプションでトークンごとに実行アクションを許可することが出来ます。
通常のチャットであれば「メッセージを送信」のみで良いと思いますが、管理者のような機能として「メッセージを削除」と「ユーザーを切断」が用意されています。
本日はメッセージ送信のみWebSocketで行います。

なお、メッセージ削除やユーザー切断はAWS SDKから操作出来ます。

クライアントアプリケーション作成

さて、ここでは最低限のUIを備えたクライアントを作ってみました。

jQueryのバージョンは3.6.0にしました。
IVS Chatを使ううえで意識するポイントとしては、WebSocketインスタンス作成時にトークンを引き渡すことと、リージョンごとのエンドポイントに注意することくらいでしょうか。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <form id="hoge-form">
        user111: 
        <input id="inputval" type="text" />
        <button type="submit">send</button>
      </form>
      <div id="received">
      </div>
    </div>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        const chatClientToken = "<hogehoge token>";
        const socket = "wss://edge.ivschat.us-west-2.amazonaws.com";
        const connection = new WebSocket(socket, chatClientToken);
        connection.onmessage = (event) => {
            const data = JSON.parse(event.data);
            $("#received").append("<div>" + data.Content + "</div>");
        };
        $("#hoge-form").on("submit", function(event) {
            event.preventDefault();
            var text   = $("#inputval")[0].value;
            const payload = {
                "Action": "SEND_MESSAGE",
                "RequestId": "HOGE",
                "Content": text
            }
            connection.send(JSON.stringify(payload));
            $("#inputval")[0].value = "";
        });
    </script>
  </body>
</html>

こちらを、S3静的ホスティングで静的コンテンツをデプロイしておきます。

実行

2つのブラウザから先程デプロイした静的コンテンツへ別々のトークンで接続してみます。
非常にシンプルですが、このような感じです。

テキストボックスにメッセージを入力してsendボタンを押すと、WebSocket接続へのsendが実行されるようになっています。試してみましょう。
user111から「aaa」というメッセージを送信しました。

別トークンのuser222の画面を確認してみます。

user222でリアルタイムに受信出来ていることが確認出来ました。
これだけなので、あとはこの繰り返しで冗長なため割愛させて頂きますが、双方向のメッセージングが簡単に実現出来ていました。
WebSocketサーバー用意しなくて良いのは最高ですね。

ちなみに、今回の実装では接続の切断などの管理を全くしておらず、トークンも静的に埋め込んでしまっているので、同じトークンを使い回すとWebSocket接続時にエラーとなります。
ご注意ください。

まとめ

Amazon IVSと分離されているところから、Amazon Chime Messaging APIとユースケースが被ってるなというのが第一印象でした。
しかし試してみると IVS Chatのユーザートークンは期間が短く、不特定多数にサッと発行してその場だけ使うような用途なのかなと感じました。
Chime Messaging APIは永続的にユーザー管理する形なので用途別に棲み分けがされていそうですね。

また、公式のサンプルリポジトリでは早速この機能を使ったデモアプリ(React)が公開されていました。
手軽にもう少し利用イメージを掴みたい方はこちらも試してみてください。