本文へスキップ

セルフホスト ​

joinVoiceRoom() には小さな Cloudflare Worker が必要です。自分のアカウントにデプロイし、費用も自分で負担します。私たちは何もホストしません。Worker はプレイヤー間の接続メッセージを中継し、人数の上限を守らせ、TURN の認証情報を発行します。音声はプレイヤー間か TURN を通り、Worker は通りません。

デプロイ ​

Cloudflare アカウントが必要です。

  1. templates/worker をプロジェクトにコピーし、そこで npm install を実行します。
  2. Cloudflare のダッシュボードの Realtime で TURN キーを作成します。キー ID と API トークンが発行されます。
  3. wrangler.jsonc の ALLOWED_ORIGINS にゲームのアドレスを設定します。
  4. シークレットを追加してデプロイします。
bash
npx wrangler secret put TURN_KEY_ID
bash
npx wrangler secret put TURN_KEY_API_TOKEN
bash
npx wrangler deploy
  1. Worker のアドレスを wss://earshot-voice.<your-subdomain>.workers.dev の形でゲームに渡します。

2 つの異なるネットワークからテストしてください。Cloudflare で使用量のアラートも設定してください。

シークレットが 2 つそろっていないと、Worker は公開 STUN サーバーだけを提供します。このとき ipPolicy: "relay" は no-turn-server で失敗します。"direct" は、ネットワークが許す範囲でプレイヤーをつなげます。

設定 ​

wrangler.jsonc の vars です。値はすべて文字列です。

変数意味テンプレートの値
ALLOWED_ORIGINS参加を許可するオリジン(カンマ区切り)。例:https://mygame.examplehttp://localhost:4710
MAX_PLAYERSルームあたりの人数。これを超えると room-full になります8
TURN_TTL_SECONDSTURN 認証情報の有効期間14400

オリジンは、スキーム、ホスト、ポートまで完全に一致する必要があり、末尾にスラッシュはつけません。開発中はローカルと本番のオリジンを並べて書いてください。

各ルームを保持する Durable Object のバインディングとマイグレーションは、すでにファイルに入っています。

canJoin ​

公開する前に、src/index.js の canJoin を編集してください。テンプレートのままでは、ルームコードを知っていれば誰でも参加でき、BAN や年齢については何もしません。false を返すと接続を拒否します。

js
async function canJoin(request, env, { room, peer }) {
  return isLoggedIn(request.headers.get("Cookie"), env); // 自分のログイン確認。
}

isLoggedIn は自分で書くコードの例です。接続 URL は joinVoiceRoom() が組み立てるので、必要な情報はリクエストのヘッダーから読んでください。拒否されたプレイヤーには connection-failed が返ります。

  • オリジンの確認で防げるのは他の Web サイトで、独自のクライアントは防げません。その気になれば、開いた Worker から TURN の認証情報を取得できます。費用が重要ならログインを必須にしてください。
  • 知らない人同士のマッチングはありません。ルームコードはフレンド向けです。モデレーションができないなら、そのままにしてください。
  • プライバシーの告知と、プレイヤーのいる地域の子どもやオンラインの安全に関する法律は、開発者の責任です。これは法的助言ではありません。詳しくはボイスを見てください。

費用 ​

費用がかかるのはリレーの設定です。これは最悪の場合の計算で、全員がリレーを使い、話し続けるとします。パケットのオーバーヘッドを含む 32 kbps の Opus で、1 ストリームあたり 1 時間に約 24 MB です。Cloudflare は TURN の送信トラフィックに対し、毎月 1,000 GB の無料枠を超えた分へ 1 GB あたり $0.05 を課金します(料金、2026-11-04 時点)。頼る前に最新の料金を確認してください。全員が全員に接続するので、n 人のルームには n x (n - 1) 本のストリームが流れます。4 人で 12 本、8 人で 56 本です。

ルーム(全員リレー)1 時間あたりの GB無料枠を超えた後の 1 時間あたりの費用無料枠で使えるルーム時間
4 人0.29$0.014約 3,470
8 人1.34$0.067約 740

実際のルームの費用はこれより少なくなります。十分に離れたプレイヤーへの送信は止まり、プッシュトゥトークはキーを離している間は無音を送るからです。無音はデータ量が少ないものの、トラフィックにはなります。この表は TURN だけの費用です。ルームサーバーの Workers と Durable Objects の使用量は別に課金されます。

トラブルシューティング ​

joined.error確認すること
connection-failedURL、次にページの正確なオリジンと ALLOWED_ORIGINS、その次に canJoin。createRoomCode() のコードは必ず Worker の形式チェックを通ります。自作のコードは英数字、-、_ で 16〜64 文字にしてください
no-turn-serverシークレットが 2 つとも設定されていることを確認し、再度デプロイします
room-fullMAX_PLAYERS