tonhowtf/omniget · error

yt-dlp not found

Error message

yt-dlp not found

What it means

Douyin's get_media_info delegates extraction to the external yt-dlp binary. Before doing anything else it calls ytdlp::find_ytdlp_cached(), and if that returns None — no yt-dlp executable was found in PATH or the known locations / cache — it fails with this anyhow error instead of attempting the extraction.

Solutions

  1. Install yt-dlp (pip install yt-dlp, brew install yt-dlp, or download the standalone binary) and ensure it is on PATH.
  2. Pass an explicit yt-dlp path in download options (opts.ytdlp_path) or pre-warm the cache via ytdlp::ensure_ytdlp(), which can auto-download the binary.
  3. Verify with `yt-dlp --version` in the same environment the app runs in (check PATH inside GUI/Tauri processes, which often differ from shell PATH).

Example fix

// before
let ytdlp_path = ytdlp::find_ytdlp_cached()
    .await
    .ok_or_else(|| anyhow!("yt-dlp not found"))?;
// after
let ytdlp_path = match ytdlp::find_ytdlp_cached().await {
    Some(p) => p,
    None => ytdlp::ensure_ytdlp().await? // auto-download on first run
};
Defensive patterns

Strategy: fallback

Validate before calling

async fn check_ytdlp() -> bool {
    tokio::process::Command::new("yt-dlp")
        .arg("--version")
        .output()
        .await
        .map(|o| o.status.success())
        .unwrap_or(false)
}

Try / catch

match platform.get_media_info(url).await {
    Err(e) if e.to_string().contains("yt-dlp not found") => {
        let path = ytdlp::ensure_ytdlp().await.context("installing yt-dlp")?;
        retry_with_ytdlp_path(url, path).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling DouyinPlatform::get_media_info(url) when ytdlp::find_ytdlp_cached() resolves to no yt-dlp binary: yt-dlp not installed, not on PATH, or the cache lookup expired and re-discovery failed.

Common situations: Fresh dev machine or Docker image without yt-dlp; yt-dlp installed under a name the finder doesn't check; user removed the cached binary path between runs; packaging a Tauri app that assumes yt-dlp is bundled but isn't.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/cf822229d8306434. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/douyin.rs:189

#[async_trait]
impl PlatformDownloader for DouyinDownloader {
    fn name(&self) -> &str {
        "douyin"
    }

    fn can_handle(&self, url: &str) -> bool {
        if let Ok(parsed) = url::Url::parse(url) {
            if let Some(host) = parsed.host_str() {
                return Self::host_matches(host);
            }
        }
        false
    }

    async fn get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {
        let ytdlp_path = ytdlp::find_ytdlp_cached()
            .await
            .ok_or_else(|| anyhow!("yt-dlp not found"))?;

        let resolved = Self::resolve_url(url).await;
        let extra = Self::extra_flags();
        let json = ytdlp::get_video_info(&ytdlp_path, &resolved, &extra).await?;

        let title = json
            .get("title")
            .and_then(|v| v.as_str())
            .unwrap_or("Douyin Video")
            .to_string();

        let author = json
            .get("uploader")
            .and_then(|v| v.as_str())
            .or_else(|| json.get("channel").and_then(|v| v.as_str()))
            .unwrap_or("Unknown")
            .to_string();

View on GitHub (pinned to 8600b91f42)