From 0d1a33236e90c68b35b59437a3d99dc80188a008 Mon Sep 17 00:00:00 2001 From: Panniantong Date: Fri, 27 Feb 2026 11:45:39 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20YouTube=20requires=20JS=20runtime=20?= =?UTF-8?q?=E2=80=94=20auto-configure=20Node.js=20in=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yt-dlp now requires an external JS runtime (deno or Node.js) for YouTube. Since agent-reach already installs Node.js, we configure yt-dlp to use it: 1. cli.py: install writes '--js-runtimes node' to ~/.config/yt-dlp/config 2. youtube.py: doctor checks JS runtime availability and config 3. SKILL.md: updated YouTube section with accurate troubleshooting Bilibili note: 412 errors are IP-based (needs proxy), not cookie-related. Fixes #47 --- agent_reach/channels/youtube.py | 26 ++++++++++++++++++++++---- agent_reach/cli.py | 19 +++++++++++++++++++ agent_reach/skill/SKILL.md | 7 ++++--- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/agent_reach/channels/youtube.py b/agent_reach/channels/youtube.py index aaae963..17332f1 100644 --- a/agent_reach/channels/youtube.py +++ b/agent_reach/channels/youtube.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- -"""YouTube — check if yt-dlp is available.""" +"""YouTube — check if yt-dlp is available with JS runtime.""" +import os import shutil from .base import Channel @@ -17,6 +18,23 @@ class YouTubeChannel(Channel): return "youtube.com" in d or "youtu.be" in d def check(self, config=None): - if shutil.which("yt-dlp"): - return "ok", "可提取视频信息和字幕" - return "off", "yt-dlp 未安装。安装:pip install yt-dlp" + if not shutil.which("yt-dlp"): + return "off", "yt-dlp 未安装。安装:pip install yt-dlp" + # Check JS runtime + has_js = shutil.which("deno") or shutil.which("node") + if not has_js: + return "warn", ( + "yt-dlp 已安装但缺少 JS runtime(YouTube 必须)。\n" + " 安装 Node.js 或 deno,然后运行:agent-reach install" + ) + # Check yt-dlp config for --js-runtimes + ytdlp_config = os.path.expanduser("~/.config/yt-dlp/config") + has_deno = shutil.which("deno") + if not has_deno and os.path.exists(ytdlp_config): + with open(ytdlp_config, "r") as f: + if "--js-runtimes" not in f.read(): + return "warn", ( + "yt-dlp 已安装但未配置 JS runtime。运行:\n" + " mkdir -p ~/.config/yt-dlp && echo '--js-runtimes node' >> ~/.config/yt-dlp/config" + ) + return "ok", "可提取视频信息和字幕" diff --git a/agent_reach/cli.py b/agent_reach/cli.py index b734130..c484416 100644 --- a/agent_reach/cli.py +++ b/agent_reach/cli.py @@ -419,6 +419,25 @@ def _install_system_deps(): except Exception: print(" ⬜ undici install failed (optional — xreach may not work behind proxies)") + # ── yt-dlp JS runtime config (YouTube requires external JS runtime) ── + if shutil.which("node"): + ytdlp_config_dir = os.path.expanduser("~/.config/yt-dlp") + ytdlp_config = os.path.join(ytdlp_config_dir, "config") + needs_config = True + if os.path.exists(ytdlp_config): + with open(ytdlp_config, "r") as f: + if "--js-runtimes" in f.read(): + needs_config = False + print(" ✅ yt-dlp JS runtime already configured") + if needs_config: + try: + os.makedirs(ytdlp_config_dir, exist_ok=True) + with open(ytdlp_config, "a") as f: + f.write("--js-runtimes node\n") + print(" ✅ yt-dlp configured to use Node.js as JS runtime (YouTube)") + except Exception: + print(" ⬜ Could not configure yt-dlp JS runtime (YouTube may not work)") + def _install_system_deps_safe(): """Safe mode: check what's installed, print instructions for what's missing.""" diff --git a/agent_reach/skill/SKILL.md b/agent_reach/skill/SKILL.md index 4b9e15b..f737290 100644 --- a/agent_reach/skill/SKILL.md +++ b/agent_reach/skill/SKILL.md @@ -93,7 +93,8 @@ xreach tweets @username --json -n 20 ### YouTube (yt-dlp) -> ⚠️ 服务器 IP 可能触发 YouTube 反爬("Sign in to confirm you're not a bot")。遇到时加 `--cookies-from-browser chrome` 或通过代理。 +> ⚠️ yt-dlp 需要 JS runtime 才能下载 YouTube。`agent-reach install` 会自动配置 Node.js 作为 runtime。 +> 如果遇到 "Sign in to confirm you're not a bot",是 IP 被 YouTube 反爬,换代理或加 cookies。 ```bash # Get video metadata @@ -106,8 +107,8 @@ yt-dlp --write-sub --write-auto-sub --sub-lang "zh-Hans,zh,en" --skip-download - # Search (yt-dlp ytsearch) yt-dlp --dump-json "ytsearch5:query" -# If blocked ("Sign in to confirm you're not a bot"): -yt-dlp --cookies-from-browser chrome --dump-json "URL" +# If "no JS runtime" warning: ensure Node.js is installed, then run: +# mkdir -p ~/.config/yt-dlp && echo "--js-runtimes node" >> ~/.config/yt-dlp/config ``` ### Bilibili (yt-dlp)