こんにちは、最近友人に誘われ Among Us
にハマっています。流行っていますよね。
オンラインで人狼のようなゲームを行う際、Discordでボイスチャットを行いながらすることが多いのですが、「追放」や「無残な姿で発見された」後には会議に参加できない特性がつきものです。
- ボイスチャットに残ってその後ゲームの様子を黙って聞く
- 別のボイスチャットに移って脱落者同士で「騙されたー!!」や「もっとできたな~」などお話しする
脱落した際はどちらかの選択を迫られることになります。
どちらも満たしたいという欲張り精神の元、『Discordのボイスチャットが別チャンネルに転送できたら様子をうかがいながらもっと楽しめるのでは??』と考え、作成することにしました。
※ 後述しますが、問題としてAudioStreamの合成ができていないので複数人で同時にしゃべった時に音声が途切れることがあり、解決策募集中です。
完成イメージ
このイメージを元に、開発していきます。
開発環境
- Node.js
12.18.4
- discord.js
12.3.1
実装
全体はこうなりました。GitHub
チャンネル選択などで大きくなってしまったので、転送のコアの部分だけここで紹介させていただきます。
転送元側のクライアントから音声を取得し、そのまま転送先のクライアントから送信しています。
// 前略
// Streamにデータを流して初期化しないと正常に動作しないようです
this.connection.from.play(new Silence(), { type: "opus" })
this.connection.to.play(new Silence(), { type: "opus" })
this.connection.from.on("speaking", (user, speaking) => {
// 転送元の誰かが発話した際のみ処理を行う
if (speaking.bitfield !== 1) return
const stream = this.connection.from.receiver.createStream(user.id)
// TODO: ここで他のStreamと合成をしたい
this.connection.to.play(stream, { type: "opus" })
})
// 後略
まとめ
脱落後も様子をうかがいながらお話ができるボイスチャットが用意できました。
Discord.jsは初めてでBotのディレクトリ構成などがまだ整っていないのでこれから調整を行います。
また、現状の問題点としてAudioStreamが合成できずに複数人が発話した際は1枠を奪い合い、途切れ途切れになってしまうというものがあります。
こちらを解決しないことにはあまり使い勝手がいいと言えないので、どうにか解決していきたいと考えています。
- marge-streamを用いた方法では、音声合成をしているわけではないので、音声が順番に繰り出されるのみで解決には至りませんでした。
- WebAudioAPIを使用した方法も考えましたが、ブラウザを触っているわけではないので取り入れることが難しいと考えています。
解決策思いついた方いらっしゃいましたらコメントやプルリクエストいただけると大変助かります🙏
皆さんもDiscord Botでよいゲームライフを!