discord.py调用FFmpeg播放音频时出现输入/输出错误求助
问题:Discord.py机器人在线播放音频中途出现I/O错误
代码实现
async def direct(self, interaction: discord.Interaction, link: str): voice_client = get(self.bot.voice_clients, guild=interaction.guild) if voice_client is None: return await interaction.response.send_message("❌ Connect to a channel first.") await interaction.response.send_message("Using direct link.") voice_client.play(discord.FFmpegPCMAudio(link)) return
错误信息
[tls @ 0x557c73a19d00] Error in the pull function. https://cdn.discordapp.com/attachments/1109998398150545410/1112473248505004142/portradio-_1_.ogg: Input/output error 2023-05-28 13:29:11 INFO discord.player ffmpeg process 1458408 successfully terminated with return code of 0.
已尝试的FFmpeg参数
ffmpeg_options = {'options': '-vn -dn -sn -ignore_unknown -fflags +discardcorrupt'}
该参数解决了"corrupt input packet"错误,但I/O问题仍存在。
需求
无需将音频文件本地存储,直接在线播放到Discord语音频道。
解决思路
1. 优化FFmpeg网络相关参数
针对网络流不稳定的问题,添加缓存、超时和自动重连参数,增强流的稳定性:
ffmpeg_options = { 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn -dn -sn -ignore_unknown -fflags +discardcorrupt -buffer_size 1024k -timeout 5000000' }
参数说明:
-reconnect 1:允许FFmpeg在连接断开时自动重连-reconnect_streamed 1:对流式传输启用重连逻辑-reconnect_delay_max 5:设置最大重连延迟为5秒-buffer_size 1024k:增大输入缓存,缓解网络波动导致的断流-timeout 5000000:设置5秒超时,避免无限等待无效连接
调用时传入参数:
voice_client.play(discord.FFmpegPCMAudio(link, **ffmpeg_options))
2. 模拟浏览器请求头
Discord CDN可能会拦截非浏览器的请求,添加用户代理头伪装成浏览器访问:
ffmpeg_options = { 'before_options': '-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" -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn -dn -sn -ignore_unknown -fflags +discardcorrupt -buffer_size 1024k' }
3. 检查网络与CDN限制
- 测试其他公开音频链接,确认是否是当前Discord CDN链接的临时限制
- 确保机器人所在服务器的网络可以稳定访问Discord CDN,无防火墙、代理或带宽限制导致的中断
4. 基于aiohttp的流式中转
如果FFmpeg直接拉流仍不稳定,可用aiohttp先获取音频流再传给FFmpeg(适合中小文件):
import aiohttp async def direct(self, interaction: discord.Interaction, link: str): voice_client = get(self.bot.voice_clients, guild=interaction.guild) if voice_client is None: return await interaction.response.send_message("❌ Connect to a channel first.") await interaction.response.send_message("Using direct link.") async with aiohttp.ClientSession() as session: async with session.get(link, headers={'User-Agent': 'Mozilla/5.0'}) as resp: if resp.status != 200: return await interaction.followup.send("Failed to fetch audio.") # 边读边传,适配大文件 voice_client.play(discord.FFmpegPCMAudio(resp.content, **ffmpeg_options))
内容的提问来源于stack exchange,提问作者PeeblYweeb
相关产品推荐
相关产品推荐

