You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Discord.py调用voice.play()无响应、YouTube音频无法播放且FFmpeg进程异常终止的问题排查

Discord.py调用voice.play()无响应、YouTube音频无法播放且FFmpeg进程异常终止的问题排查

看起来你的代码里存在几个关键问题,直接导致了音频无法播放、FFmpeg进程异常退出(返回码3436169992),我来一步步帮你排查修复:

1. 致命的音频源赋值错误(最核心问题)

你代码最后创建音频源的这一行完全写错了:

source = discord.FFmpegPCMAudio(source=source)

这里你把未定义的source变量作为参数传给了discord.FFmpegPCMAudio,相当于没有传入任何有效的音频流URL,FFmpeg自然无法处理,直接异常退出。

正确的写法是使用你之前从yt-dlp获取的url,同时必须传入你定义好的FFMPEG_OPTIONS(否则可能出现流断开、无法重连的问题):

source = discord.FFmpegPCMAudio(url, **FFMPEG_OPTIONS)

2. 语音频道连接逻辑的缺失与错误

你的代码里有个未定义的变量voice_channel,直接调用await voice_channel.connect()会报错,而且没有检查用户是否在语音频道里。修复这部分逻辑:

# 先检查用户是否在语音频道
if not ctx.author.voice:
    await ctx.send("你需要先加入一个语音频道才能让我播放音频哦!")
    return

voice_channel = ctx.author.voice.channel
voice = ctx.guild.voice_client

# 处理连接逻辑
if not voice:
    voice = await voice_channel.connect()
elif voice.channel != voice_channel:
    # 如果机器人在其他频道,可选择移动或者提示
    await voice.move_to(voice_channel)

# 停止当前正在播放的音频(如果有的话)
if voice.is_playing():
    voice.stop()

3. FFmpeg返回码3436169992的根源

这个返回码本质是FFmpeg进程因为无效的输入源(也就是你之前错误的source变量)而异常终止。当你修复了音频源的问题后,这个错误码应该会自动消失。如果之后还出现类似错误,可以检查:

  • yt-dlp获取的url是否有效(你已经加了print(url),可以手动复制到浏览器或者FFmpeg里测试能不能播放)
  • FFmpeg是否正确安装在你的服务器环境中(确保系统PATH里有FFmpeg,或者在discord.FFmpegPCMAudio里指定executable参数指向FFmpeg的路径)

4. yt-dlp配置与播放逻辑的适配优化

你的ydl_opts里配置了FFmpegExtractAudio转MP3,但因为你用了download=False,这个后处理器其实不会生效——它只在下载本地文件时工作。不过这不影响在线播放,因为你只需要获取流媒体URL,这点没问题。

但可以优化yt-dlp的错误处理,比如在解析链接时捕获更具体的异常:

# 替换原来的链接判断逻辑
try:
    # 用requests.head代替get,更快判断是否是有效链接
    response = requests.head(arg, allow_redirects=True)
    response.raise_for_status()
    info = ydl.sanitize_info(ydl.extract_info(arg, download=False))
except (requests.exceptions.RequestException, yt_dlp.utils.DownloadError) as e:
    print(f"链接解析失败,转为搜索:{e}")
    info = ydl.extract_info(f"ytsearch:{arg}", download=False)["entries"][0]

5. 增加播放错误回调,方便调试

voice.play()加上错误回调函数,能直接看到播放过程中出现的具体错误,不用只靠FFmpeg的返回码猜问题:

async def play_error(error):
    if error:
        print(f"播放过程中出现错误:{str(error)}")
        await ctx.send(f"播放出错了:{str(error)}")

# 注意要使用异步兼容的回调,这里用lambda包装
voice.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(play_error(e), self.bot.loop))

最后总结

先把最核心的音频源赋值错误修复,再补全语音连接的逻辑,这两个问题解决后,基本就能正常播放了。如果还有问题,把ydl_opts里的quiet: True改成False,打开yt-dlp的日志,结合错误回调的信息,就能快速定位到流解析或者FFmpeg的具体问题。

火山引擎 最新活动