🦊

マルチプレイヤーゲーム実況システムをAmazon Chime SDK JSで作る。 - Among Us Auto Mute -

2021/07/21に公開

こんにちは。
オリンピックの開催が間近になりましたが、最近はデジタルの界隈でもe-sportsがにわかに注目を集め始めていますね。これを後押しするというわけでもありませんが、今回はAmazon Chime SDK JSを用いてマルチプレイヤーゲームの実況配信システムを作ってみたいと思います。特に今回は、公式がファン創作についてポリシーを明確にしてくれているAmong Usを題材にしてみようと思います(ref)。

具体的には下図のようなものを作ります。中央に各ユーザのゲーム画面が表示されています。この画面を観戦者には見えるようにして、プレイヤーには見えないようにします。また音声についても同様に状況に応じて自動的にミュート/ミュート解除を行います。する必要があります。Amazon Chime SDK JSのユニークな機能を活用して、これらができるように作り込んでいきたいと思います。
image

Among UsとDiscussion

Among Usについてはいろいろなところで解説がなされているので、ここでは詳細を説明しません。ざっくりとした概要としては、宇宙人狼という異名がついている通り人狼ゲームの派生です。
4人以上のユーザが参加し、Imposterと呼ばれる狼役のユーザと、Crewと呼ばれる村人役のユーザに別れてプレイします。Crewは誰がImposterなのかわかりません。そんな中でCrewは宇宙船内で発生する宇宙船の修理などの各種タスクをこなしていきます。一方でImposterはCrewのふりをしながらそれを妨害し、本物のCrewを殺害していきます。
ImposterがCrewの生存者をImposterと同数まで減らすとImposterの勝ちです。Crewは、生存者を減らされる前に全てのタスクを完遂するか、Imposterを見つけて宇宙船外に追放すれば勝ちになります。CrewがImposterを追放するには、生存しているプレイヤー全員を集めてDiscussionを持ちかけて、Imposterを洗い出す必要があります。なお、Discussion中しかプレイヤー間でコミュニケーションをとることはできません。

AutoMuteUsと今回作るもの

通常はDiscussionはテキストチャットで行われるのですが、Imposterを追い詰めるには音声でDiscussionしたほうが緊迫感が出て面白いです(個人的な感想)。そういった要望に対し有志の方々が、ゲームと連動してDiscussion中だけボイスチャットを可能にするシステムを開発してくださっています。こういったシステムはいくつかあるようですが、AutoMuteUsと呼ばれるものが一番有名かなと思います。

AutoMuteUsは、Discordのbotです。AutoMuteUsはDiscordの機能を用いてボイスチャットを実現しています。まず、AutoMuteUsでは、AmongusCaptureと呼ばれるプログラムをもちいてAmong Usのゲーム状態を読み取ります。読み取ったゲームの状態をDiscord上のbot(AutoMuteUs)に送信してボイスチャットのon/offを制御します。
イメージとしては下の図のような構成で動いています。
image

今回、このAutMuteUsのBotの部分をAmazon Chime SDK JSを用いたプログラムに置き換えて実況配信システムを作ってみようと思います。BotはDockerコンテナやFargate上で動くプログラムとして作成します。
image

Among Us 実況配信システムの挙動

今回はAmazon Chime SDK JSを使った実況配信システムということで、プレイヤー以外に観戦者がゲーム画面と音声を受信できるようにする必要があります。
下図のように、各ユーザの画面を見られるようにしたいです。
image

今回は各ユーザ(プレイヤーと観戦者)がどの状況で画面を見れるかは次のように定義します。青の点線のユーザがゲーム画面をシェアできます。赤い点線のユーザがシェアされた画面を見ることができます。メニュー画面、ロビー画面では死亡したプレイヤーというのは存在しません。ロビー画面では、全ユーザが共有された画面を見ることができます。タスク実行中とDiscussion中は、観戦者と死亡したユーザのみが共有された画面を見ることができます。
image

音声については次のようにしたいと思います。点線の範囲がボイスチャットが有効になります。メニュー画面、ロビー画面では全員がボイスチャットできます。タスク実行中は、観戦者と死亡したユーザのみがボイスチャットできます。Discussion中は生存しているプレイヤーのみがボイスチャットできます。なお、Discussion中でも観戦者と死亡したユーザは、生存しているプレイヤーの音声を聞くことができます。
image

実現方式

システムを実現するにあたり、認証周り、S3、Lambdaなどの多くの設定、作成が必要になります。流石に全ては書ききれないので、今回は実況配信システムのために必要な特徴的な次の2つのポイントについてご紹介します。

  1. 15ユーザ分のゲーム画面の共有
  2. ゲームと連動した映像と音声の制御

その他の部分については機会があれば必要に応じて別の記事で解説したいと思います。バックエンドの構成に興味がある方は次のドキュメントに概要を記載していますので、ご確認ください。(description v.01)

なお、今回作成したものは後述するリポジトリに格納されており、簡単な操作でデプロイ可能です。ご興味のある方は是非リポジトリのReadmeをご確認ください。

15ユーザ分のゲーム画面の共有

今回のシステムでは、音声以外にもゲーム画面を配信する必要があります。
Amazon Chime SDK JSでは、画面共有機能が提供されているのですが、1会議あたり2ストリームまでとなっています。Among Usのプレイヤーは現在最大15名まで参加できますので、全員分の画面を共有することができません。一方で、ビデオ用のストリームは1会議あたり16ストリームまで(1ユーザあたり1ストリーム)使用可能です(ref)。また、(これは以前より私が度々強調しているAmazon Chime SDK JSのとても素晴らしい特徴なのですが、)ビデオ用のストリームとしてウェブカメラの映像以外にも、MediaStreamを使用可能になっています。このため、getDisplayMediaを使用してゲームのウィンドウからMediaStreamを取得して、これをビデオ用のストリームに流し込むことができます。今回はこの方法でゲーム画面の共有を行います。

なお、当然ではありますが、各ユーザのビデオストリームを使ってしまいますので、ウェブカメラの映像などを共有することはできなくなります。

ゲームと連動した映像と音声の制御

ゲームの状態はAutoMuteUsと同様にAmongusCaptureからAmazon Chime SDK JSを用いて作成されたBotが受信します。この受け取った情報を元に映像の表示/非表示と音声のミュート/ミュート解除を制御する必要があります。今回はAmazon Chime SDK JSが提供しているRealtime SignalingのData Message送信機能を用いて実現します。

動きとしては下の図のようになります。
(1)まず、AutoMuteUsと同様にAmong Usのゲーム状態をAmongus Captureで取得し、Fargate上のBotプログラムに送信します。(2)このBotプログラムはpuppeteerを用いてブラウザ(Chrome)を制御しており、受信したゲームの状態をブラウザに通知することができます。(3)ブラウザ上で動いているAmazon Chimeのクライアントは受信したゲーム状態をReatime SignalingのData Message送信機能を用いて各クライアントに送信します。各クライアントはゲーム状態に応じてマイクやスピーカーのOn/Offや画面共有のOn/Offを制御します。

なお、今回はBotはDockerイメージとして作成して、Fargateで動くようにしています。

image

デモ

今回説明した実況配信システムは下記のリポジトリに格納されています。

https://github.com/w-okada/flect-chime-sdk-demo

本実況配信システムでは、CDKを用いたスクリプトでバックエンドを構築します。AWSのアカウントがあればとても簡単にデプロイできますのでお試しください[1]。それでは、デプロイの作業を説明していきます。

前提

Setup AWS Credentials

AWSにバックエンドを構築します。このため、作業を行う前にAWSのクレデンシャルの設定ができていることを前提とします。詳細はこちらをご覧ください。

Install AWS CLI

AWS CLIを使用しますので、まだインストールしていないようでしたら、インストールしてください。詳細はこちらをご覧ください。

リポジトリをクローン

今回のデモは、blog001-multi-gameplayというBranchに作成しています。blog001-multi-gameplayを指定してcloneしてください。

$ git clone https://github.com/w-okada/flect-chime-sdk-demo.git -b blog001-multi-gameplay
$ cd flect-chime-sdk-demo/

コンフィギュレーション

今回構築するバックエンドのCloudFormationのスタック名をbackend/bin/config.tsに指定します。このスタック名は任意のものを設定できますが、この名前をPrefixとしてS3 Bucketを作成するので、グローバルでユニークなものである必要があります。

$ cat backend/bin/config.ts
export const BACKEND_STACK_NAME = 'amongus-blog-demo-xxxxx' # <-- You should change. 
export const FRONTEND_LOCAL_DEV = false # <--- Keep it
export const USE_DOCKER = false  # <--- Keep it
export const USE_CDN = true # <--- Keep it

build backend & deploy

まずはバックエンドの構築を行います。先述のとおり、CDKを用いたスクリプトで構築しますので、下記のコマンドを実施することで構築が完了します。なお、処理時間は数分かかります。

$ cd backend
$ npm install
$ npm run build_all

build frontend & deploy

次にフロントエンドをビルドしてデプロイします。下記のコマンドを実行してビルドしてください。

$ cd frontend4
$ npm install
$ npm run build

ビルドが完了したらデプロイします。

$ sh sync.sh

以上でビルドとデプロイは完了です。では、実際に使ってみましょう。

実行

デプロイしたサンプルアプリケーションのURLはdemo_url.txtに記載れています。ブラウザでアクセスしてください。

$ cat demo_url.txt

ブラウザでアクセスすると、下図の左のような画面が表示されます。画面下部のAmong Usのバナーをクリックすると下図の右の画面に切り替わります。
image

以降、サインアップをしてからサインインをします。以降の詳細は下記のマニュアルに記載してありますので、ご確認ください。
マニュアルv.01

まとめ

今回は、Amazon Chime SDK JSでマルチプレイヤーゲームの実況配信システムを作ってみました。
次の2つの特徴により、かなり簡単にシステムを実装することができたと思います。

  1. ビデオカメラ用のストリームにMediaStreamを使用できる
  2. クライアント間のデータ通信でビルトインの通信路(WebRTCのSignaling)を使用できる

これらの特徴は、ゲーム実況配信システムに限らず、いろいろなシステム/アプリケーション開発においても高い拡張性、柔軟性を提供してくれると考えています。

Disclaimer

本ブログのデモの使用または使用不能により生じたいかなる直接損害・間接損害・波及的損害・結果的損害 または特別損害についても、一切責任を負いません。

脚注
  1. 本システムはバックエンドにAWSのリソースを使用しますのでコストが発生します。ご注意ください。主に、FargateとChimeの料金です。(Fargate, Chime)。 ↩︎

Discussion