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"]}')
关键修复点说明
- 检查现有语音连接:通过
ctx.voice_client判断是否已有活跃连接,避免重复连接导致的阻塞;如果当前连接频道不符,直接移动频道而非重新连接 - 异步处理同步操作:用
asyncio.to_thread将youtube_dl的同步提取操作放到单独线程执行,不会阻塞discord.py的事件循环,解决代码停滞问题 - 优化断开逻辑:使用
play方法的after回调代替循环等待,播放结束后自动触发断开,更高效且不占用事件循环资源
内容的提问来源于stack exchange,提问作者Aarav
相关产品推荐
相关产品推荐

