Discord.py为play命令实现ytsearch及解决KeyError:formats报错
KeyError: 'formats' 核心触发原因
当使用搜索关键词查询时,youtube-dl返回的并非单个视频的元数据,而是搜索结果集合的列表级对象:
- 直接传入YouTube链接时,
extract_info()返回单视频元数据,结构包含formats、webpage_url等字段,匹配原有Video类的取值逻辑 - 传入搜索关键词时,返回结构为播放列表级别的容器,本身不存在
formats字段,所有匹配的视频元数据都嵌套在entries列表中。原有代码直接对这个容器对象取video["formats"],自然触发键不存在的报错。
另外原有代码直接取formats[0]的逻辑也存在问题:formats列表默认按清晰度从低到高排序,第0项通常是低分辨率带视频的流,并不适合音乐Bot的音频播放需求。
完整兼容实现步骤
1. 修正youtube-dl配置
替换原有简陋的配置,补充搜索、音频质量相关参数:
ytdl_options = { 'noplaylist': True, # 禁用播放列表解析,只取单个匹配结果 'default_search': 'ytsearch', # 对非URL输入强制走YouTube搜索,取第一个匹配结果 'quiet': True, # 关闭冗余的下载过程日志 'no_warnings': True, 'format': 'bestaudio/best', # 自动选择最优音频流,无需手动遍历formats数组 } ytdl = youtube_dl.YoutubeDL(ytdl_options)
2. 改造Video类适配两种返回结构
增加结构判断逻辑,统一提取单视频的元数据,不管输入是URL还是搜索关键词:
class Video: def __init__(self, query): raw_info = ytdl.extract_info(query, download=False) # 兼容搜索/播放列表的返回结构,取出嵌套的真实视频信息 if 'entries' in raw_info: video_info = raw_info['entries'][0] else: video_info = raw_info self.url = video_info["webpage_url"] self.title = video_info.get("title", "未知曲目") self.stream_url = video_info["url"]
3. 修正play命令的参数接收逻辑
原有命令定义async def play(ctx, url)只能接收无空格的单段输入,用户输入多关键词搜索时只会收到第一个单词,需要改成接收命令后全量文本的形式:
@bot.command() async def play(ctx, *, query: str): # 先校验用户是否在语音频道 if not ctx.author.voice: await ctx.send("请先加入语音频道再执行点歌操作") return # 初始化当前服务器的播放队列 if ctx.guild.id not in musics: musics[ctx.guild] = [] client = ctx.guild.voice_client # 未连接语音频道时自动加入用户所在频道 if not client: client = await ctx.author.voice.channel.connect() # 捕获搜索失败的异常,避免Bot崩溃 try: video = Video(query) except Exception: await ctx.send("未找到匹配的歌曲,请更换关键词重试") return # 处理队列逻辑 if client.is_playing() or client.is_paused(): musics[ctx.guild].append(video) await ctx.send(f"已加入播放队列:{video.title}") else: await ctx.send(f"开始播放:{video.title}") play_song(client, musics[ctx.guild], video)
长期优化提示
- 原
youtube-dl库已停止维护,可无缝替换为社区维护的yt-dlp库,接口兼容现有代码,能大幅减少流地址解析失败的问题,仅需修改导入语句即可 - 现有
play_song逻辑中需要补充FFmpeg的连接超时、重连参数,避免长连接音频播放中断 - 队列初始化时建议提前为每个已加入的服务器创建空队列,减少首次点歌的空键报错
内容的提问来源于stack exchange,提问作者user15324057
相关产品推荐
相关产品推荐

