Discord音乐机器人调用voiceclient.play(discord.FFmpegPCMAudio)无音频输出且队列失效求助
问题诱因
- 队列逻辑错误
- 你在
play_music函数启动时就直接执行self.music_queue.pop(0)弹出队首元素,同时你的/play命令大概率是每次添加歌曲后都会调用play_music,导致每新增一首歌就直接被弹出队列,查询队列时自然显示为空。 - 你没有判断当前播放状态就触发播放逻辑,正在播放时新增的歌曲会被直接弹出,不会留在队列中。
- 你在
- 播放无声音问题
discord.py的vc.play的after回调仅支持同步函数,你直接用lambda调用异步的play_next(),协程不会被正确调度,播放任务无法正常执行。- 未配置正确的FFmpeg参数,或FFmpeg版本/路径不正确,导致音频流无法正常输出。
- 控制台VC对象截断属于输出缓冲问题,不影响代码运行,无需特殊处理。
修正方案
1. 调整/play命令逻辑
新增歌曲后仅在当前未播放时才触发播放,不要每次加歌都调用play_music:
async def play_command(self, ctx, song_name): # 你的歌曲查询逻辑,得到歌曲对应的index song_item = {'index': 你的查询结果, 'title': song_name} # 加入队列末尾 self.music_queue.append([song_item, ctx.author.voice.channel]) await ctx.send("歌曲已加入队列。") # 仅未播放时触发播放 if not self.is_playing: await self.play_music()
2. 修正FFmpeg配置
确保你的FFMPEG_OPTIONS包含重连和禁用视频流参数:
FFMPEG_OPTIONS = { 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn' }
同时确认系统已安装完整版本的FFmpeg,且路径已加入环境变量,若仍有问题可以在FFmpegPCMAudio中手动指定executable参数为FFmpeg的绝对路径。
3. 修正play_music函数逻辑
调整弹出队列的时机,正确处理异步回调:
import asyncio async def play_music(self): if len(self.music_queue) == 0: self.is_playing = False return self.is_playing = True # 先取队首元素处理连接,完成后再弹出 current_song, target_vc = self.music_queue[0] index = current_song['index'] if not self.vc or not self.vc.is_connected(): self.vc = await target_vc.connect() else: await self.vc.move_to(target_vc) # 确认连接完成后再弹出队首 self.music_queue.pop(0) # 用run_coroutine_threadsafe调度异步回调 self.vc.play( discord.FFmpegPCMAudio(self.music_files[index], **self.FFMPEG_OPTIONS), after=lambda e: asyncio.run_coroutine_threadsafe(self.play_next(), self.bot.loop) )
4. 补充play_next函数逻辑
async def play_next(self): await self.play_music()
内容的提问来源于stack exchange,提问作者mm3239
相关产品推荐
相关产品推荐

