You need to enable JavaScript to run this app. discord.py/ffmpeg开发的Discord音乐机器人无音频输出问题求助
优惠活动
大模型
产品
解决方案
定价
更多

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三个特权权限,邀请机器人时也未勾选连接、说话的语音频道权限。
优化后可运行代码

运行前需要确认:

  1. 已经在Discord开发者后台的Bot页面开启了三个特权Intent权限
  2. 邀请机器人时勾选了Connect、Speak两个语音权限
  3. 本地已安装FFmpeg并配置到系统环境变量
  4. 推荐安装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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 08:09:02