You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动