如何让Discord.py音乐机器人自动播放队列中的下一首歌曲
音乐机器人自动播放下一首修复方案
核心问题
- 原有代码中
voice_channel.play()的after回调仅配置了错误打印或空逻辑,没有触发下一首歌曲的播放流程,是播放中断的核心原因 - 首次连接语音频道播放歌曲的分支,未移除已播放歌曲的队列记录,导致队列数据冗余
- 同步的
after回调无法直接执行异步播放逻辑,需要通过事件循环调度才能生效
修复实现
首先新增异步的play_next公共方法,统一处理队列读取、歌曲加载、切歌逻辑,再调整原有play方法的调用逻辑:
import asyncio playlist = [] # 新增:自动播放下一首的公共逻辑 async def play_next(ctx): voice = ctx.guild.voice_client if len(playlist) > 0 and voice and not voice.is_playing(): # 队列还有未播放内容,加载下一首 async with ctx.typing(): player = await YTDLSource.from_url(playlist[0], loop=client.loop) # 播放完成后递归调用play_next实现循环切歌 voice.play(player, after=lambda e: client.loop.call_soon_threadsafe( asyncio.create_task, play_next(ctx) ) if not e else print(f'播放错误: {e}')) await ctx.send(f'**Now playing:** {player.title}') # 更新队列信息并移除已播放项 playlist[0] = player.title playlist.pop(0) elif len(playlist) == 0: await ctx.send('播放队列已空,停止播放') @client.command(name='play', help='Plays music') async def play(ctx): voice = ctx.message.guild.voice_client def is_connected(): # Tests if bot is connected to voice channel voice_client = discord.utils.get(ctx.bot.voice_clients, guild=ctx.guild) return voice_client and voice_client.is_connected() url = ctx.message.content.lstrip('?play') url = url.lstrip(' ') playlist.append(url) if not ctx.message.author.voice: await ctx.send("You are not connected to a voice channel") playlist.pop() return else: channel = ctx.message.author.voice.channel if is_connected(): if voice.is_playing(): # 当前正在播放,仅添加到队列 index = len(playlist)-1 player = await YTDLSource.from_url(playlist[index], loop=client.loop) await ctx.send('**Added:** {} to queue'.format(player.title)) playlist[index] = player.title else: # 空闲状态直接调用play_next播放 await play_next(ctx) else: await channel.connect() # 连接成功后调用play_next播放 await play_next(ctx)
功能验证点
- 单首歌曲播放完成后会自动读取队列下一首播放
- 队列播放完成后会发送提示,不会触发报错
- 新增歌曲到队列的逻辑保持原有逻辑不变
内容的提问来源于stack exchange,提问作者Sam Sui
相关产品推荐
相关产品推荐

