Files
stream-capture/spec/quickjs_runtime.md
2025-12-02 11:59:30 -04:00

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 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:
      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.