You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js语音录制机器人指定频道无响应排查求助

Discord语音录制机器人无响应排查与修复

核心问题分析

你的机器人发送!record后无响应且无报错,主要由以下关键错误导致:

1. 频道校验逻辑完全失效

代码中错误地比较两个相同的常量,而非校验消息所在频道:

// 错误写法:两个常量值完全相同,永远不会触发return
if (messageChannelId !== allowedChannelId) {
    return;
}

// 正确写法:校验消息发送频道是否为允许的频道
if (message.channel.id !== allowedChannelId) {
    return;
}

同时你描述的校验语句if (message.Channel.Id !== allowed.Channel.Id)存在大小写错误,Discord.js中频道ID的正确调用是message.channel.id(全小写)。

2. 缺少连接错误捕获

entersState等待连接就绪时未做错误捕获,若连接超时或失败会静默终止代码,无任何日志输出:

// 错误写法:无错误捕获
await entersState(connection, VoiceConnectionStatus.Ready, 20e3);

// 正确写法:添加try/catch捕获并打印错误
try {
    await entersState(connection, VoiceConnectionStatus.Ready, 20e3);
} catch (err) {
    console.error('语音连接失败:', err);
    return message.channel.send('无法连接到语音频道,请重试');
}

3. FFmpeg模块使用错误

你引入的ffmpeg包是老旧且维护停滞的模块,应替换为fluent-ffmpeg,同时确保系统已安装FFmpeg可执行文件:

# 安装正确的模块
npm install fluent-ffmpeg

替换代码中的FFmpeg调用逻辑:

// 替换原ffmpeg引入
const ffmpeg = require('fluent-ffmpeg');

// 替换原转换逻辑
ffmpeg(`${filename}.ogg`)
    .toFormat('mp3')
    .save(`${filename}.mp3`)
    .on('end', async () => {
        await msg.edit({
            content: `🔉 Here is your recording!`,
            files: [new MessageAttachment(`./recordings/${message.author.id}.mp3`, 'recording.mp3')]
        });
        fs.unlinkSync(`${filename}.ogg`);
        fs.unlinkSync(`${filename}.mp3`);
    })
    .on('error', (err) => {
        msg.edit(`❌ 处理录音时出错: ${err.message}`);
    });

4. 录音文件格式混淆

createListeningStream中把OGG流写入了.pcm后缀的文件,实际生成的是OGG格式,需修正文件名:

// 错误写法
const filename = `./recordings/${user.id}.pcm`;

// 正确写法
const filename = `./recordings/${user.id}.ogg`;

额外检查项

  • 确保机器人拥有连接语音频道和语音活动的权限
  • 确认./recordings目录已创建,否则写入文件会失败
  • 检查机器人令牌是否正确,且机器人已加入目标服务器

修正后的关键代码片段

client.on('messageCreate', async (message) => {
    // 修复频道校验逻辑
    if (message.channel.id !== allowedChannelId) {
        return;
    }

    if (message.content.startsWith('!record')) {
        if (!message.member.permissions.has('ADMINISTRATOR')) {
            return message.channel.send('你没有使用该命令的权限');
        }

        const voiceChannel = message.member.voice.channel;
        let connection = client.voiceManager.get(message.guild.id);

        if (!connection) {
            if (!voiceChannel) {
                return message.channel.send('你必须先加入一个语音频道才能使用该命令!');
            }

            connection = joinVoiceChannel({
                channelId: voiceChannel.id,
                guildId: voiceChannel.guild.id,
                selfDeaf: false,
                selfMute: true,
                adapterCreator: voiceChannel.guild.voiceAdapterCreator,
            });

            client.voiceManager.set(message.guild.id, connection);

            // 添加连接错误捕获
            try {
                await entersState(connection, VoiceConnectionStatus.Ready, 20e3);
            } catch (err) {
                console.error('语音连接失败:', err);
                connection.destroy();
                client.voiceManager.delete(message.guild.id);
                return message.channel.send('无法连接到语音频道,请检查机器人权限或重试');
            }

            const receiver = connection.receiver;

            receiver.speaking.on('start', (userId) => {
                if (userId !== message.author.id) return;
                createListeningStream(receiver, userId, client.users.cache.get(userId));
            });

            return message.channel.send(`🎙️ 已开始录制 ${voiceChannel.name}`);
        } else {
            const msg = await message.channel.send('正在准备你的录音,请稍候...');
            await sleep(5000);

            connection.destroy();
            client.voiceManager.delete(message.guild.id);

            const filename = `./recordings/${message.author.id}`;

            // 使用fluent-ffmpeg转换格式
            ffmpeg(`${filename}.ogg`)
                .toFormat('mp3')
                .save(`${filename}.mp3`)
                .on('end', async () => {
                    await msg.edit({
                        content: `🔉 这是你的录音!`,
                        files: [new MessageAttachment(`${filename}.mp3`, 'recording.mp3')]
                    });
                    fs.unlinkSync(`${filename}.ogg`);
                    fs.unlinkSync(`${filename}.mp3`);
                })
                .on('error', (err) => {
                    msg.edit(`❌ 处理录音时出错: ${err.message}`);
                });
        }
    }
});

// 修复录音文件格式
function createListeningStream(receiver, userId, user) {
    const opusStream = receiver.subscribe(userId, {
        end: {
            behavior: EndBehaviorType.AfterSilence,
            duration: 100,
        },
    });

    const oggStream = new prism.opus.OggLogicalBitstream({
        opusHead: new prism.opus.OpusHead({
            channelCount: 2,
            sampleRate: 48000,
        }),
        pageSizeControl: {
            maxPackets: 10,
        },
    });

    const filename = `./recordings/${user.id}.ogg`;
    const out = createWriteStream(filename, { flags: 'a' });
    console.log(`👂 开始录制 ${filename}`);

    pipeline(opusStream, oggStream, out, (err) => {
        if (err) {
            console.warn(`❌ 录制文件出错 ${filename} - ${err.message}`);
        } else {
            console.log(`✅ 录制完成 ${filename}`);
        }
    });
}

内容的提问来源于stack exchange,提问作者persecue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:47:18