You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用discord.py开发音乐Discord机器人时yt-search库出现badRequest错误的解决求助

解决yt-search抛出的SearchError: badRequest问题(Discord音乐机器人)

我刚看了你的代码和问题描述,这个badRequest错误大概率是YouTube Data API密钥的问题,再加上你对yt-search的使用逻辑有点小问题,咱们一步步来解决:

1. 先搞定核心问题:有效的YouTube Data API密钥

yt-search底层依赖YouTube Data API来做搜索,你代码里写的yt_search.build("API Key")只是个占位符,必须换成真实有效的密钥:

  • 去Google Cloud控制台创建一个新项目,然后启用YouTube Data API v3
  • 生成一个API密钥,注意别给密钥加不必要的IP限制(如果你的机器人在云服务器上,得确保服务器IP在允许列表里),也不要限制API的使用范围(至少要允许YouTube Data API)
  • 把代码里的"API Key"替换成你刚拿到的真实密钥字符串

2. 修正yt-search的使用逻辑

你现在的代码里对搜索结果的处理是错的:yt.search()返回的是搜索结果列表,不是单个对象,直接调用search_result.title肯定会报错。而且你的错误捕获范围太广,应该只在输入不是YouTube链接的时候才触发搜索,而不是捕获所有下载错误。

3. 调整后的代码片段(play命令部分)

我帮你修正了play命令的关键逻辑,你可以直接替换原来的代码:

@client.command()
async def play(ctx, *, query: str = None):  # 改成*query支持带空格的标题搜索
    if query is None:
        await ctx.send("请输入YouTube视频链接或标题,格式:?play [链接/标题]")
        return
    song_there = os.path.isfile("song.mp3")
    try:
        if song_there:
            os.remove("song.mp3")
    except PermissionError:
        await ctx.send("请等待当前播放的音乐结束,或者使用?stop命令停止播放")
        return

    # 语音频道连接逻辑保持不变
    channel = discord.utils.get(ctx.guild.voice_channels, name="music lounge")
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    if voice is None or not voice.is_connected():
        voice = await channel.connect()

    ydl_opts = {
        'format': "bestaudio",
        'postprocessors': [{
            'key': "FFmpegExtractAudio",
            'preferredcodec': "mp3",
            'preferredquality': "192"
        }]
    }

    # 先判断是不是YouTube链接,不是的话再搜索
    is_youtube_link = "youtube.com" in query or "youtu.be" in query
    target_url = query

    if not is_youtube_link:
        try:
            # 初始化yt-search,用真实API密钥
            yt = yt_search.build("你的真实API密钥")
            # 搜索视频,取第一个结果
            search_results = yt.search(query, sMax=1, sType=["video"])
            if not search_results:
                await ctx.send("没有找到匹配的视频哦")
                return
            # 拿到第一个结果的视频ID,拼接成YouTube链接
            target_url = f"https://www.youtube.com/watch?v={search_results[0].videoId}"
            await ctx.send(f"找到匹配视频:{search_results[0].title},开始下载...")
        except yt_search.errors.SearchError as e:
            await ctx.send(f"搜索出错了:{str(e)}")
            return
    else:
        await ctx.send("开始下载音乐...")

    # 下载音频
    try:
        with youtube_dl.YoutubeDL(ydl_opts) as ydl:
            ydl.download([target_url])
    except Exception as e:
        await ctx.send(f"下载失败:{str(e)}")
        return

    # 重命名文件并播放
    for file in os.listdir("./"):
        if file.endswith(".mp3"):
            os.rename(file, "song.mp3")
    voice.play(discord.FFmpegPCMAudio("song.mp3"))

额外注意事项

  • 别忘了检查你的API密钥配额:YouTube Data API有每日请求配额限制,超过了也会报类似的错误,你可以在Google Cloud控制台查看配额使用情况
  • 不要把API密钥和Bot Token硬编码在代码里,最好用环境变量来管理,比如os.getenv("YOUTUBE_API_KEY")
  • 确保你的机器人运行环境能正常访问Google的API,比如如果是国内服务器,可能需要配置代理

内容的提问来源于stack exchange,提问作者user15790573

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:14:10