diff --git a/backend/Dockerfile b/backend/Dockerfile index 5a86fa2..8e019f7 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,6 +6,13 @@ RUN apt-get update && apt-get install -y ffmpeg gosu && rm -rf /var/lib/apt/list COPY backend/requirements.txt ./backend/requirements.txt RUN pip install --no-cache-dir -r backend/requirements.txt && pip install --no-cache-dir -U yt-dlp + +# nodeenv downloads a pre-built Node.js binary via pip — no apt repos needed. +# yt-dlp needs 'node' in PATH to solve YouTube's n-challenge (JS obfuscation). +RUN pip install --no-cache-dir nodeenv && \ + nodeenv --prebuilt /opt/node && \ + ln -sf /opt/node/bin/node /usr/local/bin/node + RUN echo "--cache-dir /data/yt-dlp-cache" > /etc/yt-dlp.conf COPY backend/ ./backend/ diff --git a/backend/routers/settings.py b/backend/routers/settings.py index 056c417..a0dcbc2 100644 --- a/backend/routers/settings.py +++ b/backend/routers/settings.py @@ -247,7 +247,7 @@ def ytdlp_test( "yt-dlp", "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "--dump-json", "--no-download", "--no-playlist", - "--extractor-args", "youtube:player_client=web_embedded", + "--extractor-args", "youtube:player_client=web", *cookie_args, ], capture_output=True, text=True, timeout=30, diff --git a/backend/services/ytdlp.py b/backend/services/ytdlp.py index f271a07..c58a844 100644 --- a/backend/services/ytdlp.py +++ b/backend/services/ytdlp.py @@ -216,7 +216,7 @@ def fetch_video_metadata(video_id: str) -> dict | None: base_cmd = [ "yt-dlp", url, "--dump-json", "--no-download", "--no-playlist", - "--extractor-args", "youtube:player_client=web_embedded", + "--extractor-args", "youtube:player_client=web", ] stdout, stderr, code = _run([*base_cmd, *cookie_args], timeout=30) if code != 0: @@ -567,7 +567,7 @@ def start_download( "--no-part", "--no-mtime", "-o", output_template, "--newline", "--progress", "--no-colors", - "--extractor-args", "youtube:player_client=web_embedded", + "--extractor-args", "youtube:player_client=web", *cookie_args, ], stdout=subprocess.PIPE,