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

Discord音乐bot首歌播放完成后如何自动播放queue队列内的下一首歌曲?

Discord音乐bot自动播放队列下一首实现方案

核心实现逻辑是利用VoiceClient.play()方法的after回调参数,在当前歌曲播放结束或报错时,触发下一首歌曲的加载播放流程,同时调整原play函数的执行逻辑,避免重复抢占播放资源。

核心修改点

  • 新增独立的异步play_next函数,专门负责队列下一首歌曲的加载、播放、回调绑定逻辑
  • 调整原play函数逻辑:仅当当前没有正在播放的内容时触发播放,否则仅将传入的url加入队列
  • 重写after回调逻辑,播放结束后自动触发下一首播放,而非仅打印错误

完整修改后代码

import asyncio
queue = []

async def play_next(ctx, voice_channel):
    global queue
    # 队列非空时播放下一首
    if len(queue) > 0:
        player = await YTDLSource.from_url(queue[0], loop=client.loop)
        # 绑定播放结束回调,注意after是同步回调,需要通过事件循环触发异步函数
        voice_channel.play(player, after=lambda e: (
            print('Player error: %s' % e) if e else None,
            client.loop.call_soon_threadsafe(
                asyncio.run_coroutine_threadsafe, 
                play_next(ctx, voice_channel), 
                client.loop
            )
        ))
        await ctx.send(f'**Now playing:** {player.title}')
        # 已播放的队首歌曲出列
        del queue[0]
    else:
        # 队列为空时可按需添加自动退出语音频道的逻辑
        # await voice_channel.disconnect()
        pass

@client.command(name='play',help ='Play a song',aliases=['plays', 'p'])
async def play(ctx, url):
    global queue
    server = ctx.message.guild
    voice_channel = server.voice_client
    queue.append(url)
    # 仅当前无播放内容时直接触发播放,否则仅入队
    if not voice_channel.is_playing():
        async with ctx.typing():
            await play_next(ctx, voice_channel)
    else:
        await ctx.send(f"已将歌曲加入队列,当前队列长度:{len(queue)}")

优化提示

如果你的bot需要支持多服务器同时使用,不要用全局队列,建议改成按服务器ID区分的字典存储队列,示例如下:

from collections import defaultdict
# 键为服务器ID,值为对应服务器的歌曲队列
queues = defaultdict(list)
# 后续所有操作queue的地方,都替换为queues[ctx.guild.id]即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:45:03