我有一个不和谐机器人,我希望它播放本地音乐。虽然只使用一个文件就可以做到这一点,但当我尝试播放更多歌曲时,一切都崩溃了。
client.on('voiceStateUpdate', ((oldState, newState) => { //Call it when a user enter a voice channel
if (!oldState.channel && newState.member.user !== bot) { //Discard the bot
if (newState.channelID === l5r_roleplay.id) { //If it's the right vocal channel do things
counter++; //Counter is use to check when start playing music and when everyone has left. Basically is a counter for the active members inside the vocal channel
if (counter === 1) { //It starts playing music when the first member join the vocal channel
l5r_roleplay.join().then(connection => {
let i = 0;
shuffle(music_array); //Function to shuffle array
console.log("Now playing: " + music_array[i])
connection.play(music_array[i], {volume: 0.2});
});
}
}
} else if (!newState.channel && oldState.member.user !== bot) { //Someone left
if (oldState.channelID === l5r_roleplay.id) {
counter--;
if (counter < 0) counter = 0;
if (counter === 0) {
l5r_roleplay.leave();
}
}
}
}));
上面的代码是有效的,因为它只播放第一首歌曲(music_array是一个字符串数组,其中每个字符串是歌曲名称(路径))
我想让它一个接一个地播放数组中的所有歌曲。
我尝试将其放入for循环、while循环、外部函数中。我还尝试使用返回的StreamDispatcher来处理歌曲结束时并在处理程序中增加循环/while变量,但什么都没有。
行为很简单。如果我放一个循环,它只是在控制台打印,从不播放歌曲。
一个简单的for循环示例,调度程序和控制台输出
for (let i = 0; i < music_array.length;) {
console.log("Now playing: " + music_array[i])
const dispatcher = connection.play(music_array[i], {volume: 0.2})
dispatcher.on('speaking', value => {
if (!value) i++
})
}
输出:
[nodemon] starting `node index.js`
---- < Online e operativo >
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
Now playing: ./backbone/l5r/music/The Samurai's Virtue.mp3
调度器. on()是一种非阻塞方法,这意味着它不会延迟for循环执行的每次迭代。这意味着循环将重复数百次,每次都保持在i=0,直到机器人开始/停止说话(并且机器人只会在几秒钟后这样做,给循环足够的时间在i仍然为0的时候执行数百次)。虽然从技术上讲,这不是一个无限循环,但它也会有同样的问题,因为它会尝试播放同一首歌多少次。你肯定需要使用递归循环来代替。-自杀
正如@Cann人所说,不幸的是调度器. on()是非阻塞的。
这是前一个问题的解决方案。我们需要一个递归函数
function play(voiceConnection, song, index) {
if (index === 0) {
shuffle(music_array);
song = music_array[0];
}
console.log("Now Playing: " + song);
const dispatcher = voiceConnection.play(song, {volume: 0.2})
dispatcher.on('speaking', value => {
if (!value) {
index = index+1 === music_array.length ? 0 : index+1;
play(voiceConnection, music_array[index], index);
}
})
}
第一个if用于每次使用index=0调用函数时打乱数组;这发生在我们第一次调用函数时:
play(connection, null, 0);
当我们到达播放列表的末尾时(第二个if中的第一行)。这是一个个人场景,因为我希望播放列表不仅要重新启动,还要重新洗牌。