Discord机器人无法连接语音频道(无报错)问题求助
问题分析与修复方案
你的代码存在多个拼写错误与逻辑问题,这些问题是导致机器人无法正常连接语音频道的核心原因,以下是具体问题点及修正方案:
关键错误点
- 事件函数名拼写错误:
on_massage应为on_message,Discord.py 仅识别正确命名的事件函数,此错误会导致所有消息命令完全无法触发。 - 语音属性拼写错误:
msg.author.voic.channel少了字母e,正确写法是msg.author.voice.channel,错误的属性名会触发未捕获的异常。 - 全局变量被覆盖:
?play命令中用voice_clients = await ...覆盖了全局的字典变量,导致后续操作(如播放、暂停)无法通过服务器ID正确访问语音客户端。 startswith拼写错误:?stop命令中的msg.content.startswich应为startswith,此错误会导致?stop命令无法被识别。- 缺少前置检查:未判断用户是否在语音频道、是否已连接频道等,容易触发无意义的异常。
修正后的完整代码
import discord import asyncio import youtube_dl from discord import * intents = discord.Intents.default() intents.message_content = True intents.voice_states = True client = discord.Client(intents=intents) # 注意:不要公开机器人Token,建议用环境变量存储(如os.getenv("DISCORD_BOT_TOKEN")) key = "MTA3ODY3OTcxOTIxMTQ0MjI5Nw.Gqtubx.SYqVZ7dwl8U3MpIK5mSIfXOSIi2qychJ0iddko" voice_clients = {} yt_dl_opts = {'format': 'bestaudio/best'} ytdl = youtube_dl.YoutubeDL(yt_dl_opts) ffmpeg_options = {'options': "-vn"} @client.event async def on_ready(): print(f"GOTOVO KAPITAN {client.user}") @client.event async def on_message(msg): # 修正拼写:on_massage → on_message if msg.author == client.user: return # 忽略机器人自身发送的消息 if msg.content.startswith("?play"): try: # 检查用户是否在语音频道 if not msg.author.voice: await msg.channel.send("你需要先加入一个语音频道!") return # 修正拼写:voic → voice voice_channel = msg.author.voice.channel # 检查是否已连接当前服务器的语音频道 if msg.guild.id in voice_clients: await msg.channel.send("机器人已经在语音频道中了!") return # 连接语音频道并存入全局字典 voice_client = await voice_channel.connect() voice_clients[msg.guild.id] = voice_client # 检查是否提供了歌曲URL if len(msg.content.split()) < 2: await msg.channel.send("请提供歌曲链接!") await voice_client.disconnect() del voice_clients[msg.guild.id] return url = msg.content.split()[1] loop = asyncio.get_event_loop() data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False) ) song = data['url'] player = discord.FFmpegPCMAudio(song, **ffmpeg_options, executable="C:\\ffmpeg\\bin\\ffmpeg.exe") # 开始播放歌曲 voice_clients[msg.guild.id].play(player) await msg.channel.send(f"正在播放:{data['title']}") except Exception as err: print(f"播放命令错误:{err}") # 出错时清理连接状态 if msg.guild.id in voice_clients: await voice_clients[msg.guild.id].disconnect() del voice_clients[msg.guild.id] if msg.content.startswith("?pause"): try: if msg.guild.id in voice_clients and voice_clients[msg.guild.id].is_playing(): voice_clients[msg.guild.id].pause() await msg.channel.send("已暂停播放") else: await msg.channel.send("机器人未在播放歌曲") except Exception as err: print(f"暂停命令错误:{err}") if msg.content.startswith("?resume"): try: if msg.guild.id in voice_clients and voice_clients[msg.guild.id].is_paused(): voice_clients[msg.guild.id].resume() await msg.channel.send("已恢复播放") else: await msg.channel.send("没有暂停的歌曲") except Exception as err: print(f"恢复命令错误:{err}") if msg.content.startswith("?stop"): # 修正拼写:startswich → startswith try: if msg.guild.id in voice_clients: voice_clients[msg.guild.id].stop() await voice_clients[msg.guild.id].disconnect() del voice_clients[msg.guild.id] await msg.channel.send("已停止播放并断开连接") else: await msg.channel.send("机器人未连接到语音频道") except Exception as err: print(f"停止命令错误:{err}") client.run(key)
额外说明
- 修正后的代码添加了多维度前置检查,避免无意义的异常触发,同时在出错时自动清理连接状态,防止残留无效的语音客户端。
- 建议不要将机器人Token直接写在代码中,使用环境变量存储可以有效避免Token泄露风险。
- 若仍存在连接问题,请检查机器人的服务器权限是否包含「连接语音频道」「语音活动」等必要权限。
内容的提问来源于stack exchange,提问作者Tauron
相关产品推荐
相关产品推荐

