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

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)

额外说明

  1. 修正后的代码添加了多维度前置检查,避免无意义的异常触发,同时在出错时自动清理连接状态,防止残留无效的语音客户端。
  2. 建议不要将机器人Token直接写在代码中,使用环境变量存储可以有效避免Token泄露风险。
  3. 若仍存在连接问题,请检查机器人的服务器权限是否包含「连接语音频道」「语音活动」等必要权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:20:01