【问题标题】:Having trouble getting bot to stay in voice channel and listen for commands无法让机器人留在语音频道并收听命令
【发布时间】:2026-01-04 11:10:01
【问题描述】:

您好,我正在尝试构建一个 discord 机器人,它可以使用 JavaScript 中的 AWS Polly 执行文本到语音转换。这是我第一次使用 JavaScript,我遇到了问题。我希望在 discord.js/构建不和谐机器人/用 JavaScript 编写代码方面有更多经验的人可以帮助我并提供有关如何解决此问题的见解。

以下是我的完整源代码:

var AWS = require('aws-sdk');
const Discord = require('discord.js'); 
const fs = require('fs');
var auth = require('./auth.json');

var m_currentPlaying = "";
const client = new Discord.Client();
const prefix = '$'; 
const Polly = new AWS.Polly({
    region: 'us-east-1',
    accessKeyId: auth.accessKey,
    secretAccessKey: auth.secret
});

function getTTS(msg, text) {
    var params = {
        OutputFormat: "mp3",
        Text: text,
        TextType: "text", 
        VoiceId: "Brian"
    };

    console.log("processing command:" + text);

    var fileName = 'sounds/' + msg.id + '.mp3';
    Polly.synthesizeSpeech(params, (err, data) => {
        if (err) {
            console.log("Error getting from polly");
            return err;
        }
        if (data.AudioStream instanceof Buffer) {
            fs.writeFile(fileName, data.AudioStream, function (fsErr) {
                if (fsErr) {
                    console.log("Error writing " + fileName);
                    return fsErr;
                } else {
                    console.log(fileName + ' written sucessfully');
                }
            })
        }
    });

    return fileName;
}

function deleteFile(fileName) {
    fs.unlinkSync("./" + fileName, function(err){
        if (err) {
            console.log("failed to delete " + fileName);
            console.log(err);
            return;
        } 
        console.log(fileName + ' successfully deleted');                                     
    });
}

function playSound(msg, fileName) {
    var voiceChannel = msg.member.voice.channel;
    
    voiceChannel.join()
    .then(connection => {
        m_currentPlaying = fileName; 
        const dispatcher = connection.play(fileName);
        dispatcher.on("finish", end => {
            voiceChannel.leave();
            deleteFile(fileName);
            m_currentPlaying = "";
        });
    })  
}

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});
  
client.on('message', async msg => {
    if(!msg.content.startsWith(prefix) || msg.author.bot) return; 
 
    const args = msg.content.slice(prefix.length).split(/ +/);
    const command = args.shift().toLowerCase();

    if (command === 'tts') {
        if (msg.member.voice.channel) {
            var sentence = args.join(" ");
            try {
                var file = getTTS(msg, sentence);
                console.log(file);
                playSound(msg, file);
            }
            catch(err) {
                msg.reply("There was an error with that command, I'm sorry");
                console.log(err);
                return; 
            }
        }
    }
    else if (command === 'stop') {
        if (msg.member.voice.channel) 
        {
            console.log(m_currentPlaying);
            msg.guild.voice.connection.dispatcher.destroy();
            msg.guild.voice.connection.disconnect();
            deleteFile(m_currentPlaying);
            m_currentPlaying = "";
        }
    }
});

client.login(auth.token);



现在机器人执行以下操作:

  • 机器人启动并使用我存储在 json 文件中的令牌连接到 discord api
  • 然后它等待放入 discord 中包含前缀 $ 的命令
  • 如果它看到命令“$tts”,它将确保用户在语音频道中。然后它将使用 AWS polly API 创建用户在消息中输入内容的 mp3 文件。
  • 然后它会加入discord语音频道并播放mp3文件。 mp3 文件播放完成后,它将离开语音通道并删除 mp3 文件,没有任何问题。
  • “$stop”命令也可以正常工作。它将销毁当前播放 mp3 的调度程序,断开机器人,并删除创建的 mp3 文件

问题:

  • 现在机器人运行良好,将加入语音频道,说出 tts 消息,删除 mp3 文件。但是,我希望代码做的是我希望机器人加入语音通道并留在语音通道中,准备好接收命令和播放 mp3。
  • 我希望它以节奏机器人的方式工作。 Rhythm bot 将在您的语音频道中进行环聊,并最终由于不活动的计时器而断开连接。但除此之外,机器人将留在语音频道中收听更多歌曲请求。我希望我的机器人以同样的方式行事。
  • 我尝试编写我的播放函数如下:
function playSound(msg, fileName) {
    var voiceChannel = msg.member.voice.channel;
    
    if (!msg.guild.me.voice.channel) {
        voiceChannel.join()
        .then(connection => {
            m_currentPlaying = fileName; 
            const dispatcher = connection.play(fileName);
            dispatcher.on("finish", end => {
                deleteFile(fileName);
                m_currentPlaying = "";
            });
        })
    }
    else { // else already in a voice chat 
        m_currentPlaying = fileName;
        console.log(fileName);
        const dispatcher = msg.guild.voice.connection.play(fileName);
        dispatcher.on("finish", end => {
            deleteFile(fileName);
            m_currentPlaying = "";
        });
    }
   
}

当我以这种方式编写播放函数时,我收到此错误:

似乎它在调用 fs.writeFileSync() 之前进入了 play() 函数,因此该文件还不存在,我不确定为什么。我认为这可能是同步与异步的问题,但我无法解决这个错误。感谢任何花时间查看我的代码并提供见解的人

【问题讨论】:

    标签: javascript discord.js fs


    【解决方案1】:

    如果有人从谷歌找到这个我想通了。我最终对使用缓冲区进行了更多研究,并避免一起编写 mp3 文件。这解决了这个问题,现在机器人可以在语音频道中闲逛等待传入的命令。希望这有助于为外面的人节省一些时间:)

    新代码:

    function getTTS(msg, text) {
        var params = {
            OutputFormat: "mp3",
            Text: text,
            TextType: "text", 
            VoiceId: "Brian"
        };
    
        console.log("processing command:" + text);
    
        Polly.synthesizeSpeech(params, (err, data) => {
            if (err) {
                console.log("Error getting from polly");
                return err;
            }
            if (data.AudioStream instanceof Buffer) {
                playSound(msg, data);
            }
        });
    }
    
    function playSound(msg, soundData) {
        var voiceChannel = msg.member.voice.channel;
        
        if (!msg.guild.me.voice.channel) {
            voiceChannel.join()
            .then(connection => {
                var bufferStream = new Stream.PassThrough();
                bufferStream.end(soundData.AudioStream);
                const dispatcher = connection.play(bufferStream);
                dispatcher.on("finish", end => {
                    //voiceChannel.leave();
                    //deleteFile(fileName);
                    console.log("test2");
                });
            })
        } else { // else already in a voice chat 
            var bufferStream = new Stream.PassThrough();
            bufferStream.end(soundData.AudioStream);
            const dispatcher = msg.guild.voice.connection.play(bufferStream);
            dispatcher.on("finish", end => {
                //voiceChannel.leave();
                //deleteFile(fileName);
                console.log("test1");
            });
        }  
    }
    

    【讨论】:

      最近更新 更多