Discord.py机器人音频流播放约1分30秒后中断问题求助
解决Discord.py流媒体播放1分30秒中断的问题
我之前也碰到过几乎一模一样的情况!YouTube的流媒体链接本身是临时授权的,有效期很短,而且直接用默认配置播放时,很容易因为连接超时或者被反爬机制限制导致中断——但下载后播放就没这个问题,毕竟本地文件不存在链接失效的顾虑。下面是具体的修复方案:
问题根源拆解
- YouTube返回的流媒体URL是临时权限链接,通常几分钟内就会失效,非浏览器的请求还容易被拦截
- 默认的
FFmpegPCMAudio没有开启自动重连机制,一旦链接中断就直接停止播放 - 你的youtube-dl配置没有模拟浏览器请求头,很容易被YouTube识别为非正规请求
具体修复步骤
1. 优化youtube-dl配置,添加浏览器请求头
在ydl_opts里加入模拟浏览器的请求头,同时优先选择更稳定的流媒体格式:
ydl_opts = { 'format': 'bestaudio[ext=m4a]/bestaudio/best', # 优先选稳定性更高的m4a流 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], 'http_headers': { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' }, 'nocheckcertificate': True, # 跳过证书检查,避免部分环境下的连接报错 'quiet': True, # 减少冗余输出 }
2. 给FFmpeg添加自动重连参数
创建FFmpegPCMAudio时,通过options参数开启FFmpeg的自动重连机制,让它在链接中断时自动重试:
voice.play(discord.FFmpegPCMAudio( song_info["formats"][0]["url"], options='-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' ))
这些参数的作用:
-reconnect 1:全局开启自动重连-reconnect_streamed 1:针对流媒体类型的链接开启重连-reconnect_delay_max 5:最大重连等待时间设为5秒
3. 优化语音频道连接逻辑(可选但推荐)
避免重复连接同一个语音频道,提前做检查:
voice = discord.utils.get(client.voice_clients, guild=ctx.guild) if not voice or not voice.is_connected(): if not ctx.message.author.voice: await ctx.send("你不在任何语音频道里哦!") return voiceChannel = ctx.message.author.voice.channel voice = await voiceChannel.connect()
修改后的完整play函数
async def play(ctx, *, search): # 检查是否已连接语音频道 voice = discord.utils.get(client.voice_clients, guild=ctx.guild) if not voice or not voice.is_connected(): if not ctx.message.author.voice: await ctx.send("你不在任何语音频道里哦!") return voiceChannel = ctx.message.author.voice.channel voice = await voiceChannel.connect() # 搜索YouTube视频 query_string = urllib.parse.urlencode({'search_query': search}) htm_content = urllib.request.urlopen('http://www.youtube.com/results?' + query_string) search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode()) if not search_results: await ctx.send("没找到对应的视频呀!") return url = 'http://www.youtube.com/watch?v=' + search_results[0] # 优化后的youtube-dl配置 ydl_opts = { 'format': 'bestaudio[ext=m4a]/bestaudio/best', 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], 'http_headers': { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' }, 'nocheckcertificate': True, 'quiet': True, } with youtube_dl.YoutubeDL(ydl_opts) as ydl: song_info = ydl.extract_info(url, download=False) # 添加FFmpeg重连参数 voice.play(discord.FFmpegPCMAudio( song_info["formats"][0]["url"], options='-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' )) await ctx.send(f"正在播放:{song_info['title']}")
额外小提示
- 如果发现youtube-dl很久没更新了,可以换成
yt-dlp(它是youtube-dl的活跃分支),用法几乎一致,只需要把导入改成import yt_dlp as youtube_dl就行 - 确保你的FFmpeg是最新版本,旧版本可能不支持上述重连参数
内容的提问来源于stack exchange,提问作者Aweseome245




