LoginSignup
2
1

More than 1 year has passed since last update.

【Discord.js V14】Discord BOTにVCから1人分の音声を取得して、録音する機能を実装してみる

Last updated at Posted at 2023-01-31

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

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

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

関連記事:

目次

  1. 開発環境
  2. VCから1人分の音声を取得して、録音してみる
  3. 関連記事

開発環境

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

VCから1人分の音声を取得して、録音してみる

Listener-botで音声を取得して、ファイルに書き出す処理を実装する。

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

---(以下略)---

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

---(以下略)---
  • 新しくrecord.jsを作成。中身を記述。
const { SlashCommandBuilder } = require('discord.js');
const stream = require('stream');
const fs = require('fs');
const { EndBehaviorType } = require('@discordjs/voice');
module.exports = {
	data: new SlashCommandBuilder()
        // コマンドの名前
		.setName('record')
        // コマンドの説明文
		.setDescription('VCで音声を録音します。'),
	async execute(interaction, connection) {
		connection.receiver.speaking.on('start', (userId) => {
            const audio = connection.receiver.subscribe(userId, {
                end: {
                    behavior: EndBehaviorType.AfterSilence,
                    duration: 100,
                },
            });
            var filename = './rec/'.concat(Date.now(), '-').concat(userId, '.dat');
            var out = fs.createWriteStream(filename);
            stream.pipeline(audio, out, function (err) {
                if (err) {
                    console.warn(`❌ Error recording file ${filename} - ${err.message}`);
                } else {
                    console.log(`✅ Recorded ${filename}`);
                }
            });
        });
        await interaction.reply('VCの録音を開始します!');
	},
};
  • ルートディレクトリにrecフォルダを作成し、
    node deploy-commands.jsnode index.jsを行い、Discordでコマンド/join/recordを入力。
    Listener-botのいるVCにしゃべると……
    無事recフォルダの中に録音されたファイルが作製されました!
    image.png

  • 複数人での会話を録音したい場合は、別の記事で使っている、npmのaudio-mixerを使えば取得できるはずです。

関連記事

2
1
0

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
2
1