discord.js机器人音乐队列首歌正常 切换第二首无报错停止播放
播放队列切换异常排查
核心逻辑错误
Array.shift() 方法的作用是从原数组移除第一个元素,并返回被移除的元素本身,而非返回移除元素后的新数组。你在play方法中的写法直接错误覆盖了队列结构:
if(shift) this.playQueue = this.playQueue.shift();
对应实际执行流程:
- 你添加两首歌曲后,队列初始结构为
['url1', 'url2'] - 第一首歌播放完成触发
finish事件,调用play(true, connection) - 执行
this.playQueue.shift()时,返回被移除的字符串'url1',随后this.playQueue被赋值为这个字符串,不再是数组结构 - 下一行取
this.playQueue[0]时,实际拿到的是字符串'url1'的首字符'u',传给ytdl的是无效值,直接导致播放中断。由于没有捕获音频流错误,控制台不会输出任何报错信息。
修复方案
- 修正队列出队逻辑:不需要将
shift()的返回值赋值给队列,直接调用方法修改原数组即可 - 把
finish事件绑定逻辑移到play方法内部:每次connection.play都会生成新的dispatcher实例,只给第一次生成的实例绑定事件,会导致后续播放完成后无法触发切歌逻辑 - 补充音频流错误捕获,避免无效链接直接中断流程无提示
修复后的核心代码参考:
play(shift = false, connection){ // 仅调用shift出队,不做赋值覆盖 if(shift) this.playQueue.shift(); // 生成音频流 const stream = ytdl(this.playQueue[0], { quality: 'highestaudio' }); // 捕获流错误,避免静默中断 stream.on('error', (err) => { console.error('播放流异常:', err); // 可补充自动跳过当前异常歌曲的逻辑 if(this.playQueue.length > 0) this.play(true, connection); }); this.dispatcher = connection.play(stream); this.dispatcher.setVolume(0.2); // 给新生成的dispatcher绑定切歌事件 this.dispatcher.on("finish", () => { if (this.playQueue.length > 0) { this.play(true, connection); } else { connection.disconnect(); } }); }
同时可以删除playYoutubeMusic方法中原本绑定在旧dispatcher上的重复finish事件逻辑。
内容的提问来源于stack exchange,提问作者HashtagForgotName
相关产品推荐
相关产品推荐

