当前位置: 首页 > 知识库问答 >
问题:

无法让机器人停留在语音通道中并侦听命令

方波娃
2023-03-14

您好,我正在尝试构建一个discord机器人,它可以在JavaScript中使用AWS Polly执行文本到语音转换。这是我第一次使用JavaScript,我遇到了一些问题。我希望有人有更多的不和谐经验。js/building discord bots/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文件中的令牌连接到不和谐api
  • 然后,它会在put to the disonic中等待包含前缀$的命令
  • 如果它看到命令“$tts”,它将确保用户处于语音通道中。然后它将使用AWS polly API创建一个mp3文件,其中包含用户在消息中输入的内容。
  • 然后它将加入不和谐语音频道并播放mp3文件。播放mp3文件完成后,它将离开语音频道并删除mp3文件,没有问题。
  • “$Stop”命令也可以正常工作。它将破坏当前播放mp3的调度程序,断开机器人连接,并删除创建的mp3文件

问题:

  • 现在,机器人工作得很好,将加入语音频道,说出tts消息,删除mp3文件。然而,我想要代码做的是我希望机器人加入语音通道,并留在语音通道中,准备接收命令和播放MP3
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之前进入play()函数。writeFileSync()被调用,因此该文件还不存在,我真的不知道为什么。我认为这可能是同步与异步的问题,但我在解决这个错误时遇到了麻烦。感谢所有花时间阅读我的代码并提供见解的人

共有1个答案

通奕
2023-03-14

如果有人在谷歌上找到这个,我就知道了。最后,我做了一些关于使用缓冲区和避免同时编写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");
        });
    }  
}
 类似资料:
  • 我正在尝试让我的discord机器人连接到一个语音频道,目前如下所示: 基本上,当他们发送消息时,我希望它加入消息作者的语音频道“-skip”,然后我的机器人加入,在聊天中说-p scotland forever,然后离开。我收到一条错误消息,说“频道”未定义或“连接”未定义,我尝试了几种不同的方法,我想我只是没有导入插件或其他东西,这可能是我的问题,但我知道应该使用什么插件。任何帮助都将不胜感激

  • 我为机器人制作了加入语音频道的代码, 当任何用户键入“离开”时,我希望机器人离开它所在的服务器。我该怎么做?

  • 所以最近我一直在为不和谐制作音乐机器人,但如果没有人在语音频道中超过5分钟,我想让我的机器人离开频道。目前,我的机器人仅通过停止命令断开连接 有人能帮我吗?我将不胜感激。

  • 我有一个问题,我正在使用discord.js播放音乐,但当我发送命令$stop时,我的bot没有离开语音通道,请帮助!

  • 代码: 当我使用离开命令时,机器人仍然停留在语音通道中。请帮帮我T-T

  • 我需要帮助,让我的discord机器人通过Python API的事件离开语音通道。我已经创建了一个事件,使我的机器人加入一个语音频道,如果在5秒后只有一个人出现在该频道,这部分工作。然后,如果另一个人加入或离开,我需要我的机器人离开频道。我一直想不出如何让它离开。任何帮助都将不胜感激!下面是我的方法现在的样子,需要“离开语音频道”评论的帮助: