From 43dfd6d4257928d507563011939b3202c3bc2663 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 17 Sep 2026 21:51:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor(douyin):=20=E4=B8=89=E5=B1=82=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E6=96=B9=E6=A1=88=E6=9C=80=E7=BB=88=E7=89=88=EF=BC=88?= =?UTF-8?q?App=20Feed+TikHub+apizero=EF=BC=89=EF=BC=8C=E7=A7=BB=E9=99=A4Go?= =?UTF-8?q?Downloader=EF=BC=8C=E6=B8=85=E7=90=86=E7=A1=AC=E7=BC=96?= =?UTF-8?q?=E7=A0=81Key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 P3 GoDownloader/RapidAPI(不再需要) - douyin_resolver.py: P0 App Feed(免费) → P1 TikHub → P2 apizero - API Key 全部从 os.environ 读取,无任何硬编码 - 清理 .env.example 中 RAPIDAPI_KEY 配置项 - scripts_ai.py docstring 更新 - 错误码分阶段(parse/asr/download)保留 - yt-dlp/cookies/ttwid 死代码已在前置提交删除 --- .env.example | 3 -- apps/api/app/api/routes/scripts_ai.py | 2 +- apps/api/app/services/douyin_resolver.py | 50 +++--------------------- 3 files changed, 6 insertions(+), 49 deletions(-) diff --git a/.env.example b/.env.example index a9caf4b3d..3f3eac461 100755 --- a/.env.example +++ b/.env.example @@ -205,7 +205,6 @@ DOUBAO_MAX_RETRIES=2 POINTS_ENABLED=false # ==================== 抖音解析多源轮询 (#1963) ==================== -# P0 App Feed API(免费,默认启用)→ P1 TikHub → P2 apizero → P3 GoDownloader # 无需配置 Key 也可使用(P0 免费源可用),配置 Key 可增加兜底能力 # TikHub API Key (https://tikhub.io) — $0.001/次起,注册送$0.05 @@ -214,5 +213,3 @@ TIKHUB_API_KEY= # apizero.cn API Key (https://v1.apizero.cn) — 国内抖音解析服务 APIZERO_API_KEY= -# RapidAPI Key (https://rapidapi.com) — 订阅 GoDownloader 免费层(60次/分) -RAPIDAPI_KEY= diff --git a/apps/api/app/api/routes/scripts_ai.py b/apps/api/app/api/routes/scripts_ai.py index 2851e4545..b5dd6ee98 100644 --- a/apps/api/app/api/routes/scripts_ai.py +++ b/apps/api/app/api/routes/scripts_ai.py @@ -3,7 +3,7 @@ 三个 AI 工具接口(均挂载在 /api/v1/scripts 前缀下): - POST /extract-from-douyin 从抖音视频提取文案 - 入口自动从分享文本中正则提取 http(s) URL,兼容 "复制链接" 粘贴场景 - - 多源轮询解析(douyin_resolver):App Feed API → TikHub → apizero → GoDownloader + - 多源轮询解析(douyin_resolver):App Feed API → TikHub → apizero - 拿到 MP4 直链后优先走火山 MediaKit ASR,失败回退下载+本地 ASR - ASR 空结果时使用 Feed desc 兜底,图文视频直接返回 desc - 所有源均失败时返回具体错误信息(不暴露内部细节) diff --git a/apps/api/app/services/douyin_resolver.py b/apps/api/app/services/douyin_resolver.py index fafd233ef..89b6ff992 100644 --- a/apps/api/app/services/douyin_resolver.py +++ b/apps/api/app/services/douyin_resolver.py @@ -4,10 +4,9 @@ P0: App Feed API 直连(零成本,不用 API Key,当前最稳定) P1: TikHub API(付费 $0.001/次起,稳定) P2: apizero.cn 极数本源(按量付费,国内延迟低) - P3: GoDownloader / RapidAPI(免费层 60 次/分兜底) 任一源成功即返回 MP4 直链 + 标题/文案;所有源均失败时返回 None。 -每个解析源独立超时(5-8s),总耗时不超过所有源超时之和(实际快速失败时远小于此)。 +每个解析源独立超时(5-10s),总耗时不超过所有源超时之和(实际快速失败时远小于此)。 未配置 API Key 的源自动跳过;无任何 Key 时 P0 仍可使用。 """ @@ -27,13 +26,11 @@ logger = logging.getLogger(__name__) # ── API Keys from env ────────────────────────────────────────────────── TIKHUB_API_KEY = os.environ.get("TIKHUB_API_KEY", "").strip() APIZERO_API_KEY = os.environ.get("APIZERO_API_KEY", "").strip() -RAPIDAPI_KEY = os.environ.get("RAPIDAPI_KEY", "").strip() # ── Timeouts (seconds) ──────────────────────────────────────────────── -_TIMEOUT_APP_FEED = 10 -_TIMEOUT_TIKHUB = 5 -_TIMEOUT_APIZERO = 5 -_TIMEOUT_GODOWNLOADER = 8 +_TIMEOUT_APP_FEED = 12 +_TIMEOUT_TIKHUB = 6 +_TIMEOUT_APIZERO = 6 @dataclass @@ -184,41 +181,9 @@ def _resolve_apizero(url: str, api_key: str, timeout: int = _TIMEOUT_APIZERO) -> return None -# ── Provider P3: GoDownloader (RapidAPI) ────────────────────────────── -def _resolve_godownloader(url: str, api_key: str, timeout: int = _TIMEOUT_GODOWNLOADER) -> Optional[ResolveResult]: - """GoDownloader via RapidAPI""" - if not api_key: - return None - headers = { - "X-RapidAPI-Key": api_key, - "X-RapidAPI-Host": "tiktok-download-video-no-watermark.p.rapidapi.com", - } - try: - with httpx.Client(timeout=timeout, verify=False) as c: - r = c.get( - "https://tiktok-download-video-no-watermark.p.rapidapi.com/auto", - headers=headers, - params={"url": url}, - ) - data = r.json() - video_url = ( - (data.get("video") or {}).get("url") - or data.get("video_no_watermark") - or data.get("nwm_video_url") - or "" - ) - desc = data.get("title", "") or data.get("desc", "") - if not video_url: - return None - return ResolveResult(video_url=video_url, desc=desc, source="godownloader") - except Exception as exc: - logger.warning("GoDownloader 解析失败: %s", exc) - return None - - # ── Main API ────────────────────────────────────────────────────────── def resolve_douyin_video(page_url: str) -> Optional[ResolveResult]: - """按 P0→P1→P2→P3 顺序轮询解析抖音视频。 + """按 P0→P1→P2 顺序轮询解析抖音视频。 Args: page_url: 抖音 URL 或含 URL 的分享文本。 @@ -234,7 +199,6 @@ def resolve_douyin_video(page_url: str) -> Optional[ResolveResult]: ("app_feed", lambda: _resolve_app_feed(url)), ("tikhub", lambda: _resolve_tikhub(url, TIKHUB_API_KEY)), ("apizero", lambda: _resolve_apizero(url, APIZERO_API_KEY)), - ("godownloader", lambda: _resolve_godownloader(url, RAPIDAPI_KEY)), ] enabled_count = 0 @@ -243,8 +207,6 @@ def resolve_douyin_video(page_url: str) -> Optional[ResolveResult]: continue if name == "apizero" and not APIZERO_API_KEY: continue - if name == "godownloader" and not RAPIDAPI_KEY: - continue enabled_count += 1 t0 = time.time() try: @@ -278,6 +240,4 @@ def available_providers() -> list[str]: provs.append("tikhub") if APIZERO_API_KEY: provs.append("apizero") - if RAPIDAPI_KEY: - provs.append("godownloader") return provs