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

discord.py开发Discord音乐机器人:歌曲队列与歌名搜索问题咨询

Discord.py音乐机器人功能修复方案

修复内容说明

针对你提到的两个核心问题,直接对现有代码做如下修改即可实现需求:

第一步:新增全局配置与自动切歌逻辑

在client = commands.Bot(command_prefix='!')代码行之前添加如下内容:

# 按服务器存储播放队列,key为服务器id,value为歌曲队列列表
queues = {}

async def next_song(ctx):
    # 当前服务器队列不为空则播放下一首
    if queues.get(ctx.guild.id, []):
        next_player = queues[ctx.guild.id].pop(0)
        voice_channel = ctx.guild.voice_client
        voice_channel.play(next_player, after=lambda e: asyncio.run_coroutine_threadsafe(next_song(ctx), client.loop) if e is None else print(f'播放错误: {e}'))
        await ctx.send(f'**现在播放:** {next_player.title}')

第二步:修改play命令实现队列+歌名搜索

你之前歌名搜索不准的核心原因是play命令仅接收单个参数,带空格的歌名会被截断,修改为接收完整搜索内容即可,同时添加队列逻辑,替换原有play命令代码:

@client.command(name='play', help='输入歌曲名或YouTube链接播放/加入队列')
async def play(ctx, *, search_query):
    # 检查用户是否在语音频道
    if not ctx.message.author.voice:
        await ctx.send("你还没有加入语音频道")
        return
    channel = ctx.message.author.voice.channel

    # 初始化当前服务器队列
    if ctx.guild.id not in queues:
        queues[ctx.guild.id] = []
    
    # 机器人不在语音频道则加入
    if not ctx.guild.voice_client:
        await channel.connect()
    voice_channel = ctx.guild.voice_client

    async with ctx.typing():
        # 直接传入搜索词,youtube_dl配置的default_search: auto会自动搜索匹配度最高的歌曲
        player = await YTDLSource.from_url(search_query, loop=client.loop, stream=True)
        
        # 当前正在播放则加入队列,否则直接播放
        if voice_channel.is_playing() or voice_channel.is_paused():
            queues[ctx.guild.id].append(player)
            await ctx.send(f'**已加入队列:** {player.title} (队列第{len(queues[ctx.guild.id])}位)')
        else:
            voice_channel.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(next_song(ctx), client.loop) if e is None else print(f'播放错误: {e}'))
            await ctx.send(f'**现在播放:** {player.title}')

第三步:优化stop和leave命令适配队列逻辑

替换原有stop命令:

@client.command(name='stop', help='停止播放并清空队列')
async def stop(ctx):
    voice_client = ctx.message.guild.voice_client
    if voice_client:
        # 清空当前服务器队列
        if ctx.guild.id in queues:
            queues[ctx.guild.id].clear()
        await voice_client.stop()

替换原有leave命令,加清空队列逻辑:

@client.command()
async def leave(ctx):
    # 清空当前服务器队列
    if ctx.guild.id in queues:
        queues.pop(ctx.guild.id)
    # 清空本地缓存文件
    for song in os.listdir(folder):
                file_path = os.path.join(folder, song)
                try:
                    if os.path.isfile(file_path) or os.path.islink(file_path):
                        os.unlink(file_path)
                    elif os.path.isdir(file_path):
                        shutil.rmtree(file_path)
                except Exception as e:
                    print('Failed to delete %s. Reason %s' % (file_path, e))
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    if voice and voice.is_connected():
        await voice.disconnect()
    else:
        await ctx.send("机器人未加入任何语音频道。")

功能验证

修改完成后即可实现:

  • 直接输入!play 完整歌曲名即可自动搜索匹配度最高的歌曲播放,无需拼接下划线
  • 播放过程中调用!play命令会自动将歌曲加入队列,当前歌曲播放完成后自动播放下一首
  • 无需每次播放新歌曲都手动踢出机器人重连

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:45:05