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

Discord音乐机器人无法完整播放歌曲,请求排查代码问题

问题排查与修复方案

已确认的问题点

  • FFmpeg重连配置未生效:代码中已经定义了带断流重连的ffmpeg_options参数,但初始化FFmpegPCMAudio实例时没有传入该参数,YouTube音频流存在访问时效,中途断流后没有重连逻辑就会直接停止播放
  • 代码缩进错误:if not voice_client.is_playing()所在的代码块缩进错误,不属于play函数的作用域,实际运行时逻辑执行异常
  • 异步方法调用错误:ctx.channel.send("I'm here!")是异步方法,没有添加await关键字会抛出未捕获的异步异常,可能导致进程中断、播放停止
  • 音频流地址获取方式错误:直接取info["formats"][0]["url"]无法保证拿到稳定可用的最高音质音频流,容易拿到无效或者延迟很高的流地址
  • 依赖库过时:youtube_dl已经停止维护多年,对新版YouTube的流解析适配很差,是流不稳定的核心诱因之一

修复后的完整代码

import discord
from discord.ext import commands
from discord.utils import get
# 建议将youtube_dl替换为yt-dlp,使用前执行pip install yt-dlp
from yt_dlp import YoutubeDL


bot = commands.Bot(command_prefix = ">", intents=discord.Intents.all())

@bot.event
async def on_ready():
    print("I'm ready for command")

@bot.command()
async def Help(ctx):
    emBed = discord.Embed(title = "How to use XXX Bot.", description = "This is every command you can use.", color = 0x03d7fc)
    emBed.add_field(name = ">Help" , value ="To see every command", inline = False)
    emBed.add_field(name = ">play" , value ="Play music", inline = False)
    emBed.add_field(name = ">pause" , value ="Pause music ", inline = False)
    emBed.add_field(name = ">skip" , value ="Stop music", inline = False)
    await ctx.channel.send(embed = emBed)

# 播放错误回调
async def play_error(error, ctx):
    if error:
        await ctx.send(f"播放出错:{str(error)}")

@bot.command()
async def play(ctx, url):
    channel = ctx.author.voice.channel
    voice_client = get(bot.voice_clients, guild = ctx.guild)
    
    if voice_client == None:
        await ctx.channel.send("I'm here!")
        await channel.connect()
        voice_client = get(bot.voice_clients, guild = ctx.guild)

    YDL_OPTIONS = {"format" : "bestaudio" , "noplaylist" : True, "quiet": True}
    ffmpeg_options = {"options": "-vn", "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5" }

    if not voice_client.is_playing():
        with YoutubeDL(YDL_OPTIONS) as ydl:
            info = ydl.extract_info(url, download = False)
        # 直接取解析后的最优流地址
        stream_url = info["url"]
        # 传入ffmpeg配置,添加错误回调
        voice_client.play(discord.FFmpegPCMAudio(stream_url, **ffmpeg_options), after=lambda e: bot.loop.create_task(play_error(e, ctx)))
    else:
        await ctx.channel.send("I'm playing right now")
        return

bot.run("你的机器人TOKEN")

注意事项

  • 运行前需确认已经安装了FFmpeg并配置到系统环境变量中
  • 旧版discord.py需要开启意图权限,在Discord开发者后台的机器人设置页打开所有Privileged Gateway Intents开关
  • 如果仍然使用原youtube_dl,只需将导入语句改回即可,但还是建议尽快替换为yt-dlp保证解析稳定性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:18:03