{"record":{"id":"2919cc4f35c221ba","repo":"tonhowtf/omniget","slug":"failed-to-start-ffmpeg","errorCode":null,"errorMessage":"Failed to start ffmpeg: {}","messagePattern":"Failed to start ffmpeg: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ffmpeg.rs","lineNumber":346,"sourceCode":"    }\n\n    if let Some(ref extra) = opts.additional_output_args {\n        args.extend(extra.clone());\n    }\n\n    args.extend([\n        \"-progress\".to_string(),\n        \"pipe:1\".to_string(),\n        \"-nostats\".to_string(),\n        opts.output_path.clone(),\n    ]);\n\n    let mut child = crate::core::process::command(\"ffmpeg\")\n        .args(&args)\n        .stdout(std::process::Stdio::piped())\n        .stderr(std::process::Stdio::piped())\n        .spawn()\n        .map_err(|e| anyhow!(\"Failed to start ffmpeg: {}\", e))?;\n\n    let stdout = child\n        .stdout\n        .take()\n        .ok_or_else(|| anyhow!(\"No stdout from ffmpeg\"))?;\n    let reader = BufReader::new(stdout);\n    let mut lines = reader.lines();\n\n    let cancel = cancel_token.clone();\n    let progress = progress_tx.clone();\n    let line_reader = tokio::spawn(async move {\n        while let Ok(Some(line)) = lines.next_line().await {\n            if cancel.is_cancelled() {\n                break;\n            }\n            if let Some(us) = parse_out_time_us(&line) {\n                if total_duration_us > 0 {\n                    let pct = (us as f64 / total_duration_us as f64 * 100.0).min(100.0);","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ffmpeg.rs#L328-L364","documentation":"convert() spawns the ffmpeg binary as a child process via crate::core::process::command. If spawn() fails — the binary is missing, not executable, or cannot be launched — the OS error is wrapped into this anyhow error. It indicates the conversion never started.","triggerScenarios":"Calling convert (or the download pipeline that uses it) when ffmpeg is not installed, not on PATH, or lacks execute permission in the target environment (e.g. bundled Tauri app without sidecar binaries).","commonSituations":"Clean CI/container images without ffmpeg; macOS/Windows packaging where the sidecar binary wasn't shipped; PATH differing between dev shell and GUI-launched app; antivirus/executable-permission blocks.","solutions":["Install ffmpeg (apt install ffmpeg / brew install ffmpeg / choco install ffmpeg) or bundle it as a Tauri sidecar.","Verify `ffmpeg -version` runs in the same environment the app executes in (check PATH for GUI vs shell).","Check the binary's execute permission bit if ffmpeg is shipped alongside the app.","Call is_ffmpeg_available() before convert and surface a clear setup message to the user."],"exampleFix":"// before\nlet mut child = crate::core::process::command(\"ffmpeg\")\n    .args(&args)\n    .spawn()\n    .map_err(|e| anyhow!(\"Failed to start ffmpeg: {}\", e))?;\n// after\nif !is_ffmpeg_available().await {\n    anyhow::bail!(\"ffmpeg is not installed or not on PATH; install it or configure FFMPEG_PATH\");\n}\nlet mut child = crate::core::process::command(\"ffmpeg\")\n    .args(&args)\n    .spawn()\n    .map_err(|e| anyhow!(\"Failed to start ffmpeg: {} (PATH={:?})\", e, std::env::var(\"PATH\")))?;","handlingStrategy":"fallback","validationCode":"// before calling convert/embed_metadata\nif !is_ffmpeg_available().await {\n    return Err(anyhow!(\n        \"ffmpeg is required: install it (apt/brew/choco install ffmpeg) or bundle as sidecar\"\n    ));\n}","typeGuard":"async fn ffmpeg_ready() -> bool {\n    tokio::process::Command::new(\"ffmpeg\")\n        .arg(\"-version\")\n        .output()\n        .await\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","tryCatchPattern":"match convert(/* ... */).await {\n    Err(e) if e.to_string().contains(\"Failed to start ffmpeg\") => {\n        ui::prompt_ffmpeg_install(); // guide user instead of raw error\n    }\n    other => other?,\n}","preventionTips":["Check availability once at app startup and show a setup banner early","For Tauri apps, ship ffmpeg as a sidecar and resolve its absolute path","Never assume GUI process PATH equals developer shell PATH"],"tags":["ffmpeg","process-spawn","missing-binary","path"],"backgroundTag":"command-not-found","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}