# 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](https://github.com/quickjs-ng/quickjs) * **Storage Location:** The user's AppData `bin` directory (same as `yt-dlp`). * Windows: `%APPDATA%\StreamCapture\bin\` * macOS: `~/Library/Application Support/StreamCapture/bin/` * **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` ### 2.2. Download & Update Logic * **Check:** On app launch (or `init_ytdlp`), check if `qjs` exists. * **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`). * **Permissions:** On macOS/Linux, ensure `chmod +x` is applied. * **Update:** When `update_ytdlp` is triggered, also check/redownload the latest `qjs` binary. ### 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 qjs` to the `yt-dlp` command. * **Environment Modification:** Before spawning the `yt-dlp` child process in Rust, dynamically modify its `PATH` environment variable. * **Action:** Prepend the absolute path of the application's `bin` directory to the system `PATH`. * **Result:** When `yt-dlp` looks for `qjs`, it will find it in the injected `PATH`. ## 3. Implementation Plan ### Step 1: Refactor `src-tauri/src/ytdlp.rs` * Rename file/module to `src-tauri/src/binary_manager.rs` (Optional, or just expand `ytdlp.rs`). * Add constants/functions for QuickJS: * `get_qjs_binary_name()` * `download_qjs()`: Similar logic to `download_ytdlp` but parsing QuickJS release assets. ### Step 2: Update `src-tauri/src/commands.rs` * Update `init_ytdlp` to initialize **both** binaries. * Update `update_ytdlp` to update **both** binaries. ### Step 3: Update `src-tauri/src/downloader.rs` * In `download_video` and `fetch_metadata`: 1. Resolve the absolute path to the `bin` directory. 2. Read the current system `PATH`. 3. Construct a new `PATH` string: `bin_dir + delimiter + system_path`. 4. Configure the `Command`: ```rust Command::new(...) .env("PATH", new_path) .arg("--js-runtime") .arg("qjs") ... ``` ## 4. Acceptance Criteria 1. **File Existence:** `qjs.exe` (Win) or `qjs` (Mac) appears in the `bin` folder after app startup. 2. **Process Execution:** The logs show `yt-dlp` running successfully. 3. **Verification:** If a specific video requires JS interpretation (often indicated by slow downloads or errors without JS), it proceeds smoothly. 4. **Clean Logs:** No "PhantomJS not found" or "JS engine not found" warnings in the logs.