Discord音乐机器人接近歌曲结尾时突然停止播放问题排查
Discord音乐机器人无法完整播放歌曲的问题排查与解决
问题描述
测试机器人播放歌曲《Yesterday》(全长2分32秒)时,在1分48秒突然停止播放;队列中其他歌曲也存在同样的无法完整播放的问题,终端输出无错误信息。
可能原因与解决方案
1. YouTube音频流断流(最可能原因)
YouTube的m3u8音频流可能存在临时中断,默认的FFmpeg配置没有自动重连机制,导致播放中途停止。
解决方法:更新FFmpeg参数,添加自动重连选项
修改代码中的FFMPEG_OPTIONS:
FFMPEG_OPTIONS = { 'options': '-vn -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' }
参数说明:
-reconnect 1:允许FFmpeg在连接断开时重连-reconnect_streamed 1:针对流式传输启用重连-reconnect_delay_max 5:最大重连延迟5秒
2. YouTube请求被限制
yt-dlp默认的请求头可能被YouTube识别为非浏览器请求,导致获取的音频流不稳定或中途被切断。
解决方法:为yt-dlp添加浏览器请求头
修改代码中的YDL_OPTIONS:
YDL_OPTIONS = { 'format': 'bestaudio', 'noplaylist': True, 'http_headers': { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' } }
3. yt-dlp版本过时
旧版本的yt-dlp可能存在YouTube解析的兼容性问题,导致获取的音频流地址不稳定。
解决方法:更新yt-dlp到最新版本
执行命令:
pip install --upgrade yt-dlp
4. 异常回调未处理错误
当前代码的after回调没有处理播放过程中的异常,可能出现错误后静默停止播放,且无日志输出。
解决方法:在回调中添加异常捕获与日志输出
修改play_next方法中的播放代码:
def after_play(error): if error: print(f"播放出错: {error}") self.client.loop.create_task(self.play_next(ctx)) ctx.voice_client.play(source, after=after_play)
修改后的完整代码示例
import discord from discord.ext import commands import yt_dlp import asyncio import os from dotenv import load_dotenv from pathlib import Path from random import randint intents = discord.Intents.default() intents.members = True intents.message_content = True intents.voice_states = True dotenv_path = Path('C:/Users/tr/OneDrive/phytoncinali/discordbot/venv/bot/.env') load_dotenv(dotenv_path=dotenv_path) TOKEN = os.getenv('DISCORD_TOKEN') # 更新FFmpeg参数,添加自动重连 FFMPEG_OPTIONS = { 'options': '-vn -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' } # 添加浏览器请求头,避免被限制 YDL_OPTIONS = { 'format': 'bestaudio', 'noplaylist': True, 'http_headers': { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' } } class MusicBot(commands.Cog): def __init__(self, client): self.client = client self.queue = [] @commands.command() async def play(self, ctx, *, search): voice_channel = ctx.author.voice.channel if ctx.author.voice else None if not voice_channel: return await ctx.send("Seste değilsin gerizekalı") if not ctx.voice_client: await voice_channel.connect() async with ctx.typing(): with yt_dlp.YoutubeDL(YDL_OPTIONS) as ydl: info = ydl.extract_info(f"ytsearch:{search}", download=False) if 'entries' in info: info = info['entries'][0] url = info['url'] title = info['title'] self.queue.append((url, title)) await ctx.send(f'birazdan **{title}** söyleyeceğim') if not ctx.voice_client.is_playing(): await self.play_next(ctx) async def play_next(self, ctx): if self.queue: url, title = self.queue.pop(0) source = await discord.FFmpegOpusAudio.from_probe(url, **FFMPEG_OPTIONS) # 添加错误处理的回调函数 def after_play(error): if error: print(f"播放错误: {error}") self.client.loop.create_task(self.play_next(ctx)) ctx.voice_client.play(source, after=after_play) await ctx.send(f'şimdi **{title}** söyleyeceğim') elif not ctx.voice_client.is_playing(): await ctx.send("söylenecek şarkı kalmmadı") @commands.command() async def skip(self, ctx): if ctx.voice_client and ctx.voice_client.is_playing(): ctx.voice_client.stop() await ctx.send("geçtim bunu o zaman") bot = commands.Bot(command_prefix='!', intents=intents) async def main(): await bot.add_cog(MusicBot(bot)) await bot.start(TOKEN) asyncio.run(main())
内容的提问来源于stack exchange,提问作者Cinasli
相关产品推荐
相关产品推荐

