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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:18:01