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
相关产品推荐
相关产品推荐

