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

discord.py机器人语音频道无音频:connect后代码卡顿求助

Discord.py 机器人连接语音频道后代码停滞的问题修复

核心问题分析

你的代码出现停滞,主要有两个关键原因:

  • 未检查机器人是否已在目标语音频道建立连接,重复调用await voice_channel.connect()会引发阻塞或异常
  • youtube_dl是同步库,在异步函数中直接调用会阻塞整个事件循环,导致后续代码无法执行,这才是你看到“代码暂停/无限循环”的根本原因

另外,你尝试用线程运行connect的做法错误,因为connect是异步协程,必须通过await调用,不能直接丢入线程执行。

修复后的完整代码

import asyncio
import youtube_dl
from discord.ext import commands
from youtube_search import YoutubeSearch

@bot.command()
async def play(ctx, *, query):
    # 检查用户是否在语音频道
    if not ctx.author.voice:
        await ctx.send("你未连接到任何语音频道。")
        return

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

    # 检查是否已有活跃连接,没有则创建
    if not voice_client or not voice_client.is_connected():
        voice_client = await voice_channel.connect()
    # 如果当前连接的频道不是目标频道,移动过去
    elif voice_client.channel != voice_channel:
        await voice_client.move_to(voice_channel)

    # 获取YouTube搜索结果
    results = YoutubeSearch(query, max_results=1).to_dict()
    if not results:
        await ctx.send("未找到相关结果。")
        return

    audio_url = "https://www.youtube.com" + results[0]['url_suffix']

    # 用asyncio.to_thread包装同步的youtube_dl操作,避免阻塞事件循环
    ydl_opts = {
        'format': 'bestaudio/best',
        'quiet': True,
        'default_search': 'auto',
        'source_address': '0.0.0.0'
    }

    def extract_audio_info():
        with youtube_dl.YoutubeDL(ydl_opts) as ydl:
            return ydl.extract_info(audio_url, download=False)

    info = await asyncio.to_thread(extract_audio_info)
    url = info['url']
    source = await discord.FFmpegOpusAudio.from_probe(url, method='fallback')

    # 停止当前播放(如果有),开始新播放
    if voice_client.is_playing():
        voice_client.stop()

    # 定义播放结束后的回调函数,自动断开连接
    def after_playing(error):
        asyncio.run_coroutine_threadsafe(voice_client.disconnect(), bot.loop)

    voice_client.play(source, after=after_playing)

    # 发送播放确认消息
    await ctx.send(f'正在播放:{info["title"]}')

关键修复点说明

  1. 检查现有语音连接:通过ctx.voice_client判断是否已有活跃连接,避免重复连接导致的阻塞;如果当前连接频道不符,直接移动频道而非重新连接
  2. 异步处理同步操作:用asyncio.to_thread将youtube_dl的同步提取操作放到单独线程执行,不会阻塞discord.py的事件循环,解决代码停滞问题
  3. 优化断开逻辑:使用play方法的after回调代替循环等待,播放结束后自动触发断开,更高效且不占用事件循环资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 16:02:49