Discord机器人提取YouTube音频发送失败:文件缓冲区报错排查
问题分析与解决
错误根源
- 文件名获取逻辑错误:
subprocess.check_call返回的是进程退出状态码(成功时为0),并非命令输出内容。你用它获取文件名,导致变量s的值为0,后续open(s, 'rb')实际打开的是标准输入流(文件描述符0),这就是报错里File buffer <_io.BufferedReader name=0>的核心原因。 - 未使用正确文件路径:你已经通过
find函数找到了文件的实际路径g,但发送文件时却误用了错误的s变量。
修正方案
步骤1:正确获取文件名
替换check_call为subprocess.check_output(异步场景推荐用asyncio.create_subprocess_shell),它会返回命令的标准输出内容,处理掉换行符后再添加.mp3后缀。
步骤2:使用正确的文件路径
发送文件时,直接使用find函数返回的有效路径,而非错误的s变量。
步骤3:优化异步执行(推荐)
同步调用subprocess会阻塞Discord机器人的事件循环,改用异步执行命令可避免机器人卡顿,同时兼容Discord.py的异步架构。
修正后的代码
Finder File 保持不变
def find(file): for root, dirs, files in os.walk(os.getcwd()): for filename in files: if filename == file: return os.path.join(root, file)
Main File 修正版
import asyncio import subprocess import os import discord from discord.ext import commands @bot.command(description="Downloads songs from youtube and sends it") async def youtube_song(ctx, url): await ctx.send("Starting... __[MIGHT TAKE A MINUTE]__") # 异步执行youtube-dl下载音频,避免阻塞机器人 download_cmd = f'youtube-dl -x --extract-audio --audio-format mp3 --output %(title)s.%(ext)s "{url}"' process = await asyncio.create_subprocess_shell( download_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) await process.communicate() # 异步获取原始文件名并处理 filename_cmd = f'youtube-dl --get-filename "{url}"' process = await asyncio.create_subprocess_shell( filename_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) output, _ = await process.communicate() base_filename = output.decode('utf-8').strip() target_filename = f"{base_filename}.mp3" # 查找文件的完整路径 file_path = find(target_filename) if not file_path: await ctx.send("Failed to find the downloaded file.") return await ctx.channel.send("Audio is ready.") # 使用正确路径发送文件 await ctx.channel.send(file=discord.File(file_path))
额外说明
- 给URL添加引号(
"{url}"),避免URL含特殊字符导致命令执行失败。 - 异步执行命令能保证机器人在下载音频时仍可响应其他指令,提升用户体验。
内容的提问来源于stack exchange,提问作者High_Bread
相关产品推荐
相关产品推荐

