ボイス
ボイス系のボット(Lavalink や @discordjs/voice を含む)はコードの変更なしで動きます。GameVox は Discord のボイスゲートウェイプロトコルをそのまま話し、AEAD-RTP のストリームを合成ピアとしてネイティブの WebRTC SFU にブリッジします。
対応ライブラリ
- Lavalink v3 + v4(Java。JDA / discord4j などを介して前段に置く JVM ボット)
- @discordjs/voice(Node)
- discord.py のボイス拡張(
PyNaCl) - JDA のオーディオモジュール
- discord4j
- Eris(オプションのボイス依存を含む)
エンドポイント
リージョンごとに用意されています。ボットは VOICE_SERVER_UPDATE のディスパッチが指定したリージョンに接続します。
compatible-voice-gateway-us.gamevox.comcompatible-voice-gateway-eu.gamevox.comcompatible-voice-gateway-ap.gamevox.com
メインゲートウェイが、チャンネルの SFU の場所に応じて適切なリージョンを配信します。ライブラリはディスパッチの endpoint を読んでそこへ接続するだけで、手動のルーティングは不要です。
接続の流れ
- ボットがメインゲートウェイ(
gateway.gamevox.com)にchannel_id付きでop:4 Update Voice Stateを送信します。 - メインゲートウェイが、エンドポイントとセッションごとのトークンを含む
VOICE_STATE_UPDATEとVOICE_SERVER_UPDATEを配信します。 - ボットが
wss://{endpoint}/?v=8に WSS 接続し、{server_id, user_id, session_id, token}を付けてop:0 Identifyを送信します。 - ボイスゲートウェイが
ssrc、ip、port、対応する暗号化モードを含むop:2 Readyを返します。 - ボットが UDP の IP ディスカバリーを行います(74 バイトの type
0x0001パケット → type0x0002でエコーバック)。 - ボットが選んだ暗号化モードを付けて
op:1 Select Protocolを送信します。 - ボイスゲートウェイが 32 バイトの
secret_keyを含むop:4 Session Descriptionを返します。 - ボットが、合意した方式で AEAD 暗号化した Opus を RTP で送信します。
暗号化モード
Discord と同じく、2 つの AEAD-RTPSize モードに対応します。
aead_aes256_gcm_rtpsize— 推奨。暗号化ペイロードの末尾に付与した 4 バイトのカウンターから nonce を導出する AES-256-GCM です。aead_xchacha20_poly1305_rtpsize— AES-NI がないライブラリ向けのフォールバックです。
旧来のモード(xsalsa20_poly1305、_lite、_suffix)は提供していません。Discord が 2024 年に廃止し、主要なライブラリも移行済みです。ライブラリが古いモードに固定されている場合は更新してください。
Lavalink についての注意
Lavalink は VOICE_SERVER_UPDATE から直接 endpoint を読み、自分で UDP を張ります。エンドポイントに到達できる限り(到達できます)、Lavalink は相手が Discord でないことに気づきません。
テスト済みバージョン: Lavalink v3.7.x と v4.0.x。特定のバージョンで問題が起きた場合は開発者ポータルから報告してください。CI でそのバージョンを固定して検証します。
レイテンシの目標
ブリッジによる追加レイテンシの目標は、受信 UDP から SFU 送出までで 5 ms 未満です。5 ms を超えると音楽が不自然に聞こえます(音の立ち上がりのずれ、ハイハットのジッター)。ブリッジは Opus をそのまま通し、トランスコードしないため、主な要素は復号と再パケット化です。
発話イベント
op:5 Speaking は双方向で、Discord と同一です。ボイスゲートウェイは受信した人間の話者の SSRC をユーザー ID に対応付け、ボットが紐づけられるよう {ssrc, user_id} を含む op:5 を配信します。
きれいに終了する
メインゲートウェイに channel_id: null で op:4 Update Voice State を送るとセッションが終了します。ボイスゲートウェイは UDP ソケットを閉じ、合成 SFU ピアを取り除くため、聞いている人には直ちに音声が届かなくなります。
まだ未対応
- DAVE / E2EE — Discord のチャンネル単位のエンドツーエンド暗号化ボイスモード。時期は未定です。
- サウンドボード — ボットはサウンドボードの音を再生できません。
- ステージチャンネル — ワイヤー上は受け付けますが、聴衆と登壇者を分けて扱う仕組みはありません。