提问者:小点点

不和谐JS,VoiceConnection.play()与本地音乐播放列表中断


我有一个不和谐机器人,我希望它播放本地音乐。虽然只使用一个文件就可以做到这一点,但当我尝试播放更多歌曲时,一切都崩溃了。

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

共1个答案

匿名用户

调度器. 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中的第一行)。这是一个个人场景,因为我希望播放列表不仅要重新启动,还要重新洗牌。