You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

discord.py音乐机器人队列异常:歌曲结束后队列不更新

Discord.py 音乐机器人队列问题修复

问题现象

  • 执行skip命令跳歌时,tracks字典会被一次性删除两个元素
  • 歌曲自然播放结束后,队列展示未同步更新,仍显示已结束的歌曲为当前播放曲目

问题根源

原代码中queueCheck函数仅在self.skipping为True时才更新tracks列表,导致歌曲自然结束时没有移除已播放完的曲目;同时skip逻辑与队列弹出的同步性差,造成重复删除。

修复后的代码

核心修复:queueCheck函数

def queueCheck(self, ctx, id, vc):
    text = ""
    if queues[id] != []:       # 服务器队列不为空
        # 弹出下一个要播放的流
        stream = queues[id].pop(0)
        # 不管是自然结束还是跳过,都移除已播放完的当前曲目
        tracks[id].pop(0)
        # 如果还有剩余曲目,设置播放提示文本
        if len(tracks[id]) != 0:
            text = f"Now playing **{tracks[id][0]}**"
        # 播放下一首
        vc.play(stream, after=lambda e: self.queueCheck(ctx, id, vc))
    else:
        # 队列为空时,清空tracks并提示
        if id in tracks:
            tracks.pop(id)
        text = "Queue has finished playing!"   
    # 发送提示消息
    coro = ctx.send(text)
    fut = asyncio.run_coroutine_threadsafe(coro, self.client.loop)
    try:
        fut.result()
    except:
        pass

修复skip命令

@commands.command(name='skip', help="Skips the current song")
async def skip(self, ctx):
    if ctx.author.voice is None:
        return await ctx.send('You are not in a voice channel!')
    # 直接停止当前播放,由queueCheck处理后续逻辑
    ctx.voice_client.stop()
    self.isPaused = False

优化play命令初始化逻辑

确保首次播放时tracks和queues的初始化一致:

@commands.command(name='play', help="Plays any song", aliases=['pl'])
async def play(self, ctx, *, url):
    if ctx.author.voice is None:
        return await ctx.send('You are not in a voice channel!')
    if ctx.voice_client is None:
        await ctx.author.voice.channel.connect()
    
    vc = ctx.guild.voice_client
    guild_id = ctx.message.guild.id
    if not vc.is_playing() and not self.isPaused:
        stream = await self.playSong(ctx, url)
        # 初始化队列和曲目列表
        queues[guild_id] = [stream]
        # tracks已经在playSong中初始化,这里直接发送播放提示
        await ctx.send(f'Playing **{tracks[guild_id][0]}**')
        vc.play(stream, after=lambda e: self.queueCheck(ctx, guild_id, vc))
    else:
        await self.queue(ctx, url)

修复说明

  1. 统一曲目更新逻辑:在queueCheck中,每次处理下一首歌曲前,先从tracks中移除已播放完的曲目,确保tracks与实际播放状态完全同步,不管是自然结束还是跳过操作。
  2. 移除冗余标记:删除self.skipping变量,简化逻辑,避免因标记状态不同步导致的错误。
  3. 队列清空处理:当播放队列耗尽时,清空对应服务器的tracks条目,避免展示残留的旧曲目。
  4. 同步队列展示:由于showQueue函数依赖tracks列表的第一个元素作为当前播放曲目,只要tracks同步更新,队列展示就会自动显示正确的当前播放内容。

内容的提问来源于stack exchange,提问作者Virat Chauhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:10:30