イントロダクション
本記事では、DiscordのBotをVoice Channel(VC)に参加させ、VC内でローカルに用意したmp3ファイルを再生するプログラムについて記述しています。なお、Discord.jsのバージョンはv14です。
本記事の対象者
- DiscordBotを動作させたことがある。
- DiscordBotを利用してVC上に音声を再生したい。
筆者環境
環境 | Version | 備考 |
---|---|---|
Node.js | v16.18.0 | |
TypeScript | v4.9.5 | |
discord.js | v14.7.1 | 基本パッケージ |
dotenv | v16.0.3 | Botトークン保存用 |
@discordjs/voice | v0.14.0 | VCを扱うパッケージ |
ffmpeg-static | v5.1.0 | @discordjs/voiceの依存 |
tweetnacl | v1.0.3 | @discordjs/voiceの依存 |
Visual Studio Code | v1.75.1 |
本記事のBotは以下のようなファイル構造を保持しているとします。
.
├─ build
| ├─ sounds
| | └─ melody.mp3
| └─ main.js
|
├─ node_modules
| └─ etc.
├─ src
| └─ main.ts
├─ .env
└─ etc.
モジュールのインストール
以下の記事でdiscord.js+TypeScriptの導入方法について丁寧に説明して下さっています。
なお本記事のファイル/フォルダの構成や、コマンド等については上述の記事を参考にしています。
初めに基本となるdiscord.js
と、dotenv
を導入します。
npm install discord.js dotenv
次にVCで音声を再生するために必要なパッケージを導入します。
npm install @discordjs/voice ffmpeg-static tweetnacl
プログラムの説明
VCのあるサーバーにおいて、任意のテキストチャンネルで
!play
と送信するとBotがVCに参加し、mp3音源を再生します。再生が終了するとBotはVCから退出します。
mp3ファイルは./build/soundsフォルダに格納します。
!play
を送信する前にVCには最低一人が参加している状態としてください。
本プログラムでは誰もいないVCにBotは参加できません。
プログラム本体
import fs from 'node:fs'
import path from 'node:path'
import { Client, Message, Events, GatewayIntentBits } from 'discord.js'
import { entersState, AudioPlayerStatus, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType, NoSubscriberBehavior } from '@discordjs/voice'
import dotenv from 'dotenv'
dotenv.config()
const soundPath: string = path.join(__dirname, 'sounds');
const soundFiles: string[] = fs.readdirSync(soundPath).filter(file => file.endsWith('.mp3'));
let soundFilePath: { [key: string]: string } = {};
for (const file of soundFiles) {
const extractExtension: string = file.split('.')[0];
const filePath: string = path.join(soundPath, file);
soundFilePath[extractExtension] = filePath;
}
const client = new Client({
intents: [ GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates
]
});
client.once(Events.ClientReady, (c: Client) => {
console.log(`Ready! Logged in as ${c.user?.tag}`);
});
client.on(Events.MessageCreate, async (message: Message) => {
if (message.author.bot) {
return;
}
if (!message.content.startsWith('!play')) {
return;
}
const channel = message.member?.voice.channel;
if (!channel) {
await message.reply('[ERR] Someone needs to be on the voice channel.');
return;
}
const connection = joinVoiceChannel({
adapterCreator: channel.guild.voiceAdapterCreator,
channelId: channel.id,
guildId: channel.guild.id,
selfDeaf: true,
selfMute: false,
});
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Pause,
},
});
connection.subscribe(player);
const resource = createAudioResource(soundFilePath['melody'],
{
inputType: StreamType.Arbitrary,
}
);
player.play(resource);
await entersState(player,AudioPlayerStatus.Playing, 10 * 1000);
await entersState(player, AudioPlayerStatus.Idle, 24 * 60 * 60 * 1000);
connection.destroy();
});
client.login(process.env.TOKEN);
TOKEN='YOUR_BOT_TOKEN'
Botの実行
先述の参考記事の通りであれば、次に示すnpm run
コマンドを利用してコンパイルします。
ファイル名やフォルダの名前は適宜読み替えてください。
npm run compile
または、
tsc -p .
コンパイルが完了したら以下のコマンドでBotを実行します。
npm run start
または
node ./build/main.js
Botを起動できたら、VCに参加して、任意のテキストチャンネルで!play
と入力し送信してください。正しく動作していれば、Botがあなたが参加しているVCに参加し、指定した音声を再生します。再生が終わると退出します。
音声が再生されている途中に!play
を送信すると再生状態が上書きされます。すなわち再生される音声は同じものがまた最初から再生される動作となります。
Botが正しく動作しない場合、BotがVCから退出しないことがあります。その場合はdiscordから手動にて退出を行ってください。PC版であれば、VCチャンネルのBotを右クリックすると退出させる操作が可能です。ただしサーバーの管理者権限が必要なことに注意してください。
BotがVCに参加して、一瞬で退出する場合は、再生したいmp3ファイルのパス指定がうまくいっていない可能性があります。console.log()
等を利用してcreateAudioResource()
の第一引数に正しくパスが指定されているか確認してみてください。
まとめ
本記事ではDiscordBotでmp3ファイルを再生するプログラムを紹介しました。今回はローカルに用意したmp3ファイルを使用しましたが、インターネット上のファイルや、Youtubeといった動画共有サービスの動画音声を再生することも可能です。こちらについては読者に検索いただきたい。
参考になるリンク等
・@discordjs/voice Documentation
・Youtubeの音源を再生する方法