Switch bundled yt-dlp to a Python venv with curl_cffi for impersonation

The previous standalone PyInstaller binary couldn't run `--impersonate`
because curl_cffi isn't packaged into it. Bundled mode lost the
bot-detection bypass as a result.

Install layout is now:
  ~/.local/share/yt-offline/
    bin/deno              ← unchanged: prepended to PATH for JS deciphering
    venv/bin/yt-dlp       ← new: pip-installed yt-dlp[default] + curl_cffi

The install script:
- Errors clearly if python3 or the `venv` module isn't available
  (the latter is split out on Debian as `python3-venv`).
- Creates the venv if missing, otherwise reuses it for upgrades.
- pip-installs `yt-dlp[default]` and `curl_cffi`, both with PyPI's
  built-in SHA-256 verification.
- Cleans up the legacy `bin/yt-dlp` PyInstaller binary if a prior
  install left one behind.
- Probes `--list-impersonate-targets` at the end and logs whether
  curl_cffi loaded successfully.

Downloader::apply_impersonation now passes --impersonate
unconditionally — both bundled (via the venv) and system yt-dlp (via
pip-installed curl_cffi) honor it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-05-24 23:17:27 -07:00
parent 26bf619a23
commit 770ef66623
3 changed files with 148 additions and 124 deletions

View file

@ -1255,13 +1255,11 @@ async fn get_preview(
} else if !browser.is_empty() && browser != "none" {
cmd.arg("--cookies-from-browser").arg(&browser);
}
// Only attach --impersonate if the active yt-dlp supports it. Our
// bundled (PyInstaller) binary doesn't ship curl_cffi, so the flag
// would error out. System yt-dlp installed via pip with curl_cffi
// does support it.
if !use_bundled {
cmd.arg("--impersonate").arg("Chrome-146:Macos-26");
}
// The bundled venv install now ships `curl_cffi` (see
// `crate::ytdlp_bin::install_command`), so --impersonate works in both
// bundled and system modes.
let _ = use_bundled;
cmd.arg("--impersonate").arg("Chrome-146:Macos-26");
let output = cmd
.arg(&url)
.stdin(Stdio::null())