3.6 KiB
3.6 KiB
Feature Specification: QuickJS Runtime Integration for yt-dlp
1. Context & Objective
yt-dlp increasingly relies on a JavaScript runtime to execute complex decryption scripts (e.g., signature extraction) required by YouTube and other platforms. Without a JS runtime, downloads may fail or be throttled.
The objective is to automatically manage the QuickJS runtime binary (download, update, store) alongside the existing yt-dlp binary and configure the download process to utilize it via environment variable injection.
2. Technical Requirements
2.1. Binary Management
The application must manage the QuickJS binary lifecycle identically to how it currently handles yt-dlp.
- Source Repository: https://github.com/quickjs-ng/quickjs
- Storage Location: The user's AppData
bindirectory (same asyt-dlp).- Windows:
%APPDATA%\StreamCapture\bin\ - macOS:
~/Library/Application Support/StreamCapture/bin/
- Windows:
- Unified Naming on Disk:
Regardless of the source filename, the binary must be renamed upon saving to ensure consistent invocation:
- Windows:
qjs.exe - macOS:
qjs
- Windows:
2.2. Download & Update Logic
- Check: On app launch (or
init_ytdlp), check ifqjsexists. - Download: If missing, fetch the appropriate asset from the latest GitHub release of
quickjs-ng/quickjs.- Note: Logic must detect OS/Arch to pick the correct asset (e.g.,
windows-x86_64,macos-x86_64/arm64).
- Note: Logic must detect OS/Arch to pick the correct asset (e.g.,
- Permissions: On macOS/Linux, ensure
chmod +xis applied. - Update: When
update_ytdlpis triggered, also check/redownload the latestqjsbinary.
2.3. Execution & Environment Injection
To enable yt-dlp to find the qjs binary without hardcoding absolute paths in the flags (which can be fragile), we will modify the subprocess environment.
- Command Flag: Always pass
--js-runtime qjsto theyt-dlpcommand. - Environment Modification:
Before spawning the
yt-dlpchild process in Rust, dynamically modify itsPATHenvironment variable.- Action: Prepend the absolute path of the application's
bindirectory to the systemPATH. - Result: When
yt-dlplooks forqjs, it will find it in the injectedPATH.
- Action: Prepend the absolute path of the application's
3. Implementation Plan
Step 1: Refactor src-tauri/src/ytdlp.rs
- Rename file/module to
src-tauri/src/binary_manager.rs(Optional, or just expandytdlp.rs). - Add constants/functions for QuickJS:
get_qjs_binary_name()download_qjs(): Similar logic todownload_ytdlpbut parsing QuickJS release assets.
Step 2: Update src-tauri/src/commands.rs
- Update
init_ytdlpto initialize both binaries. - Update
update_ytdlpto update both binaries.
Step 3: Update src-tauri/src/downloader.rs
- In
download_videoandfetch_metadata:- Resolve the absolute path to the
bindirectory. - Read the current system
PATH. - Construct a new
PATHstring:bin_dir + delimiter + system_path. - Configure the
Command:Command::new(...) .env("PATH", new_path) .arg("--js-runtime") .arg("qjs") ...
- Resolve the absolute path to the
4. Acceptance Criteria
- File Existence:
qjs.exe(Win) orqjs(Mac) appears in thebinfolder after app startup. - Process Execution: The logs show
yt-dlprunning successfully. - Verification: If a specific video requires JS interpretation (often indicated by slow downloads or errors without JS), it proceeds smoothly.
- Clean Logs: No "PhantomJS not found" or "JS engine not found" warnings in the logs.