LoginSignup
1
1

More than 1 year has passed since last update.

【Discord.js V14】Discord BOTにVCに音楽を流す機能を実装してみる

Last updated at Posted at 2023-01-31

皆さん初めまして。Morichanと申します。
下記の※の記述を理解したうえで、記事を読んでください。

※DiscordBot開発初心者の書いた記事です。
(また、プログラミング自体、2年ほどのブランクあり)

BOTをVCに参加させるまでの流れに関しては、別の記事にまとめてあります。

関連記事:

目次

  1. 開発環境
  2. VCに音楽を流す機能を実装してみる
  3. 関連記事

開発環境

OS (Windows11)
discord.js (14.7.1)
node.js (18.13.0)
npm (8.19.3)
@discordjs/voice (^0.14.0)

VCに音楽を流す機能を実装してみる

Speaker-botを使って、VCに音楽を流してみます。

  • index.js内部のBOT(今回はSpeaker-bot)の記述を改変する。
// GatewayIntentBits.GuildVoiceStatesを追加しないと、VCに入ってから音を取得したり流したりなどの処理ができない。
const client2 = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] });
  • join.jsから、return connection2;でVCの情報を受け渡すコードを追記。
			await interaction.reply('VCに参加しました!');
			return connection2;
		}
		else {
			await interaction.reply('BOTを参加させるVCを指定してください!');
		}
	},
};
  • index.jsでコマンドの判定を行い、commandの値が、
    joinの時、connection = await command.execute(interaction, client1, client2);で受け取り、
    playの時、await command.execute(interaction, connection);play.jsに値を受け渡す。
let connection = null;

---(以下略)---

	try {
        // コマンドを実行
		if (interaction.commandName === 'join') {
			connection = await command.execute(interaction, client1, client2);
		}
		else if (interaction.commandName === 'play') {
			await command.execute(interaction, connection);
		}
		else {
			await command.execute(interaction);
		}
	} catch (error) {
		console.error(error);
		await interaction.reply({ content: 'コマンドを実行中にエラーが発生しました。', ephemeral: true });
	}
});

---(以下略)---
  • VSCordのターミナルで、参考資料をもとに、
    npm i discord.js @discordjs/voice @discordjs/opus sodiumまたは、npm i discord.js @discordjs/voice @discordjs/opus tweetnaclを実行。
    ※Windowsの場合、前者だとエラーが出る恐れがあるらしいので、その際は後者を実行。

  • 新しくplay.jsを作成。参考資料をもとに、中身を記述。
    正直、下のほうの記述は、player.play(resource);connection.subscribe(player);さえあれば動きます。

const { createAudioPlayer, NoSubscriberBehavior, createAudioResource, StreamType, AudioPlayerStatus, VoiceConnectionStatus, entersState } = require('@discordjs/voice');
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
	data: new SlashCommandBuilder()
        // コマンドの名前
		.setName('play')
        // コマンドの説明文
		.setDescription('VCで音楽を流します。'),
	async execute(interaction, connection) {
		const resource = createAudioResource(
			'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
			{
                // OPUS型で渡す時はArbitrary
				inputType: StreamType.Arbitrary,
			},
		);
		const player = createAudioPlayer({
			behaviors: {
				noSubscriber: NoSubscriberBehavior.Pause,
			},
		});
		player.play(resource);
        // (以下)エラーが出て音声が無事に流れなかった場合、動いているかの確認を取りやすくするために記述。
		const status = ['●Loading Sounds...', '●Connecting to VC...'];
		const p = interaction.reply(status.join('\n'));
		const promises = [];
		promises.push(entersState(player, AudioPlayerStatus.AutoPaused, 1000 * 10).then(() => status[0] += 'Done!'));
		promises.push(entersState(connection, VoiceConnectionStatus.Ready, 1000 * 10).then(() => status[1] += 'Done!'));
		await Promise.race(promises);
		await p;
		await Promise.all([...promises, interaction.editReply(status.join('\n'))]);
		connection.subscribe(player);
		await entersState(player, AudioPlayerStatus.Playing, 100);
		await interaction.editReply('Playing'); // これは必須。
		await entersState(player, AudioPlayerStatus.Idle, 2 ** 31 - 1);
		await interaction.editReply('End');
	},
};
  • node deploy-commands.jsnode index.jsを行い、Discordでコマンド/join/playを入力。
    ヘッドホンをつけてSpeaker-botのいるVCに
    無事音楽が流れました!
    image.png

  • ルートディレクトリに再生したいmp3ファイルがある場合は、
    'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'の部分を
    join(__dirname, '../001.mp3')のように書き換える。

関連記事

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1