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

Discord Bot无报错但功能失效:无法退语音频道及播放音频

问题描述

我是编程新手,正在制作Discord Bot,目标实现Bot加入语音频道、播放MP3音频后退出。目前遇到两个问题:

  • 执行!leave命令无报错,但Bot不会退出语音频道
  • 执行!mo命令Bot能加入频道,但无法播放音频

环境信息:

  • Python 3.7.9
  • Visual Studio Code
  • FFmpeg已加入系统路径,MP3文件位置确认无误,但FFmpeg版本与教程不同

以下是我的代码:

import discord
from discord.ext import commands
from discord import FFmpegPCMAudio

TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

intents = discord.Intents.default()
intents.members = True

client = commands.Bot(command_prefix= '!', intents=intents)

@client.event
async def on_ready():
    print("ITS WORKING")
    print("------------------------")

@client.command()
async def hello(ctx):
    await ctx.send("ITS WORKING")

@client.command(pass_context=True)
async def join(ctx):
    if (ctx.author.voice):
        channel = ctx.message.author.voice.channel
        await channel.connect()

    else:
        await ctx.send("You are not in a voice channel, you must be in a voice channel to run this command")

@client.command(pass_context=True)
async def leave(ctx):
    if (ctx.voice_client):
        await ctx.guild.voice_client.disconnect()
        await ctx.send("I left the voice channel")
    else:
         await ctx.send("I am not in a voice channel")

@client.command(pass_context=True)
async def mo(ctx):
    if (ctx.author.voice):
        channel = ctx.message.author.voice.channel
        voice = await channel.connect()
        source= FFmpegPCMAudio('mo.mp3')
        player = voice.play(source)

    else:
        await ctx.send("You are not in a voice channel")

client.run(TOKEN)
解决方案

1. 修复!leave命令无法退出频道的问题

当前代码中判断ctx.voice_client存在,但调用的是ctx.guild.voice_client.disconnect(),虽然多数情况下两者指向同一对象,但存在上下文不一致的潜在风险。直接使用ctx.voice_client断开连接更稳妥:

@client.command(pass_context=True)
async def leave(ctx):
    if ctx.voice_client:
        await ctx.voice_client.disconnect()
        await ctx.send("I left the voice channel")
    else:
         await ctx.send("I am not in a voice channel")

2. 修复!mo命令无法播放音频的问题

针对不同原因的修复方案:

  • 显式指定FFmpeg路径:即使已加入系统路径,版本差异可能导致调用失败,直接指定可执行文件路径规避问题:
# Windows示例
source = FFmpegPCMAudio('mo.mp3', executable='C:/Program Files/ffmpeg/bin/ffmpeg.exe')
# Linux/macOS示例
# source = FFmpegPCMAudio('mo.mp3', executable='/usr/bin/ffmpeg')
  • 添加播放等待逻辑:voice.play()是非阻塞操作,Bot可能因无后续任务提前结束进程,导致音频无法播放。添加等待播放完成的逻辑,还可实现播放后自动退出:
# 顶部需导入asyncio
import asyncio

@client.command(pass_context=True)
async def mo(ctx):
    if ctx.author.voice:
        channel = ctx.author.voice.channel
        # 避免重复连接频道
        if not ctx.voice_client:
            voice = await channel.connect()
        else:
            voice = ctx.voice_client
        
        source = FFmpegPCMAudio('mo.mp3')
        voice.play(source)
        
        # 等待音频播放完成
        while voice.is_playing():
            await asyncio.sleep(1)
        
        # 播放结束后自动退出
        await voice.disconnect()
        await ctx.send("音频播放完成,已退出频道")
    else:
        await ctx.send("You are not in a voice channel")
  • FFmpeg兼容性参数:部分MP3文件含冗余视频流,添加-vn参数忽略视频流,避免解析错误:
source = FFmpegPCMAudio('mo.mp3', options='-vn')

额外注意事项

  • 确保Discord Bot拥有语音相关权限:在开发者平台Bot设置中勾选Voice Members,邀请Bot到服务器时确认权限齐全。
  • 检查MP3文件编码:特殊编码的MP3可能无法被FFmpeg识别,可使用命令转换为标准格式:
ffmpeg -i mo.mp3 -codec:a libmp3lame -qscale:a 2 fixed_mo.mp3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:17:33