discord.py/ffmpeg开发的Discord音乐机器人无音频输出问题求助
问题定位
你的代码存在多个核心逻辑错误导致无音频输出,具体问题如下:
- 重复实例化机器人:同时创建了
bot和client两个机器人实例,实际运行的bot没有配置正确的intents,Discord v2.x以上版本必须开启voice_states、message_content权限才能正常处理语音和消息命令。 - 未存储语音客户端实例:
on_ready中连接语音频道后没有保存返回的VoiceClient对象,play命令中调用的voice_client、voice、vc均为未定义变量,无法正常调用播放接口。 - 调用废弃API:
create_ytdl_player是discord.py v1.x的废弃接口,v2.x版本已完全移除该方法,需要自行搭配youtube_dl和FFmpegPCMAudio实现播放逻辑。 - 无效冗余代码:
play函数中的await message.content.startswith('play')完全无效,message变量未定义,且命令触发由框架自动处理不需要额外判断前缀。 - 权限配置缺失:未在Discord开发者后台开启
Server Members Intent、Voice States Intent、Message Content Intent三个特权权限,邀请机器人时也未勾选连接、说话的语音频道权限。
优化后可运行代码
运行前需要确认:
- 已经在Discord开发者后台的Bot页面开启了三个特权Intent权限
- 邀请机器人时勾选了
Connect、Speak两个语音权限 - 本地已安装FFmpeg并配置到系统环境变量
- 推荐安装
yt-dlp替代旧的youtube_dl,兼容性更好
import discord from discord.ext import commands from discord import FFmpegPCMAudio import yt_dlp as youtube_dl TOKEN = "替换为你的机器人Token" # 配置所需权限 intents = discord.Intents.default() intents.members = True intents.voice_states = True intents.message_content = True bot = commands.Bot(command_prefix='s', intents=intents) # 全局存储语音客户端实例 voice_client = None # YTDL播放配置 ytdl_format_options = { 'format': 'bestaudio/best', 'restrictfilenames': True, 'noplaylist': True, 'nocheckcertificate': True, 'quiet': True, 'no_warnings': True, 'default_search': 'auto', 'source_address': '0.0.0.0' } # FFmpeg配置 ffmpeg_options = { 'options': '-vn' } ytdl = youtube_dl.YoutubeDL(ytdl_format_options) class YTDLSource(discord.PCMVolumeTransformer): def __init__(self, source, *, data, volume=0.5): super().__init__(source, volume) self.data = data self.title = data.get('title') @classmethod async def from_url(cls, url, *, loop=None, stream=False): loop = loop or bot.loop data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream)) if 'entries' in data: data = data['entries'][0] filename = data['url'] if stream else ytdl.prepare_filename(data) return cls(FFmpegPCMAudio(filename, **ffmpeg_options), data=data) @bot.event async def on_ready(): global voice_client # 启动时自动连接指定语音频道 channel = discord.utils.get(bot.get_all_channels(), id=794444804607574026) if channel and isinstance(channel, discord.VoiceChannel): voice_client = await channel.connect() print(f"登录成功,当前身份为 {bot.user}") @bot.command(name='play') async def play(ctx, url): global voice_client # 未连接语音时自动加入命令发送者所在频道 if not voice_client or not voice_client.is_connected(): if not ctx.author.voice: await ctx.send("你需要先加入一个语音频道") return voice_client = await ctx.author.voice.channel.connect() # 停止当前播放内容 if voice_client.is_playing(): voice_client.stop() # 加载音频并播放 async with ctx.typing(): player = await YTDLSource.from_url(url, loop=bot.loop, stream=True) voice_client.play(player, after=lambda e: print(f'播放错误: {e}') if e else None) await ctx.send(f'正在播放: {player.title}') @bot.command(name='leave') async def leave(ctx): global voice_client if voice_client and voice_client.is_connected(): await voice_client.disconnect() voice_client = None await ctx.send("已退出语音频道") bot.run(TOKEN)
内容的提问来源于stack exchange,提问作者Superior125
相关产品推荐
相关产品推荐

