diff --git a/backend/services/ytdlp.py b/backend/services/ytdlp.py index 6e4abdc..e606243 100644 --- a/backend/services/ytdlp.py +++ b/backend/services/ytdlp.py @@ -386,45 +386,36 @@ def fetch_channel_links(channel_id: str) -> list[str]: def fetch_video_comments(youtube_video_id: str, max_comments: int = 20) -> list[dict]: - """Fetch top comments via yt-dlp Python API. Returns empty list on failure.""" - import yt_dlp as _yt_dlp + """Fetch top comments via yt-dlp CLI writing to a temp file. Returns empty list on failure.""" + import os + import tempfile - with _cookies_lock: - cf = _cookies_file - b = _cookies_browser - oauth2 = _use_oauth2 + url = f"https://www.youtube.com/watch?v={youtube_video_id}" - ydl_opts = { - "quiet": True, - "no_warnings": True, - "skip_download": True, - "getcomments": True, - "extractor_args": { - "youtube": { - "max_comments": [str(max_comments), str(max_comments)], - "comment_sort": ["top"], - } - }, - } - if oauth2: - ydl_opts["username"] = "oauth2" - ydl_opts["password"] = "" - elif cf and Path(cf).exists(): - ydl_opts["cookiefile"] = cf - else: - for candidate in _AUTO_COOKIES_PATHS: - if Path(candidate).exists(): - ydl_opts["cookiefile"] = candidate + with tempfile.TemporaryDirectory() as tmpdir: + out_tmpl = os.path.join(tmpdir, "%(id)s.%(ext)s") + args = [ + "yt-dlp", url, + "--write-info-json", + "--write-comments", + "--extractor-args", f"youtube:max_comments={max_comments};comment_sort=top", + "--no-download", + "--no-playlist", + "--quiet", + "--output", out_tmpl, + *_cookie_args(), + ] + _run(args, timeout=90) + + info = None + for fname in os.listdir(tmpdir): + if fname.endswith(".info.json"): + try: + with open(os.path.join(tmpdir, fname)) as f: + info = json.load(f) + except Exception: + pass break - else: - if b and not cf: - ydl_opts["cookiesfrombrowser"] = (b,) - - try: - with _yt_dlp.YoutubeDL(ydl_opts) as ydl: - info = ydl.extract_info(f"https://www.youtube.com/watch?v={youtube_video_id}", download=False) - except Exception: - return [] if not info: return []