{"record":{"id":"f4727de517be0e78","repo":"tonhowtf/omniget","slug":"ffmpeg-not-available","errorCode":null,"errorMessage":"ffmpeg not available","messagePattern":"ffmpeg not available","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ffmpeg.rs","lineNumber":444,"sourceCode":"pub struct MetadataEmbed {\n    pub title: Option<String>,\n    pub artist: Option<String>,\n    pub album: Option<String>,\n    pub track_number: Option<String>,\n    pub genre: Option<String>,\n    pub year: Option<String>,\n    pub comment: Option<String>,\n    pub thumbnail_url: Option<String>,\n}\n\npub async fn embed_metadata(\n    file: &Path,\n    metadata: &MetadataEmbed,\n    embed_thumbnail: bool,\n    http_client: &reqwest::Client,\n) -> anyhow::Result<()> {\n    if !is_ffmpeg_available().await {\n        return Err(anyhow!(\"ffmpeg not available\"));\n    }\n\n    let temp_dir = file.parent().unwrap_or(Path::new(\".\"));\n    let ext = file.extension().and_then(|e| e.to_str()).unwrap_or(\"mp4\");\n    let temp_output = temp_dir.join(format!(\".omniget_meta_{}.{}\", uuid::Uuid::new_v4(), ext));\n\n    let is_audio_only = matches!(\n        ext.to_lowercase().as_str(),\n        \"mp3\" | \"m4a\" | \"aac\" | \"ogg\" | \"opus\" | \"flac\" | \"wav\" | \"wma\"\n    );\n\n    let thumbnail_path = if embed_thumbnail && is_audio_only {\n        if let Some(ref url) = metadata.thumbnail_url {\n            match download_thumbnail(http_client, url, temp_dir).await {\n                Ok(p) => Some(p),\n                Err(e) => {\n                    tracing::warn!(\"Failed to download thumbnail: {}\", e);\n                    None","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ffmpeg.rs#L426-L462","documentation":"embed_metadata() first checks is_ffmpeg_available() and aborts with this plain error if ffmpeg cannot be located. It is a deliberate pre-flight guard so callers get a clear message before any temp files are created.","triggerScenarios":"Calling embed_metadata (post-download metadata/thumbnail embedding) on a machine without ffmpeg installed or with ffmpeg absent from the PATH of the running Tauri process.","commonSituations":"End-user machines without ffmpeg; GUI apps launched from Finder/Explorer where PATH differs from the shell; misconfigured FFMPEG_PATH-like overrides; Docker images without ffmpeg.","solutions":["Install ffmpeg on the target machine or bundle it as a sidecar binary with the app.","Check `ffmpeg -version` works from the same environment the app runs in (GUI PATH != shell PATH).","Expose the availability check in UI before download completes so users can install ffmpeg first.","Document the ffmpeg requirement in setup/install instructions."],"exampleFix":"// before\nif !is_ffmpeg_available().await {\n    return Err(anyhow!(\"ffmpeg not available\"));\n}\n// after\nif !is_ffmpeg_available().await {\n    return Err(anyhow!(\n        \"ffmpeg not available: install ffmpeg (https://ffmpeg.org) or add it to PATH; \\\n         embedding skipped\"\n    ));\n}","handlingStrategy":"validation","validationCode":"// gate metadata embedding before the whole download pipeline\nif !is_ffmpeg_available().await {\n    return Err(anyhow!(\n        \"ffmpeg not available; install ffmpeg or disable metadata embedding\"\n    ));\n}","typeGuard":"async fn can_embed_metadata() -> bool {\n    is_ffmpeg_available().await\n}","tryCatchPattern":"match embed_metadata(/* ... */).await {\n    Err(e) if e.to_string() == \"ffmpeg not available\" => {\n        log::info!(\"skipping metadata embed: ffmpeg missing\");\n        // keep the downloaded file, just skip embedding\n    }\n    other => other?,\n}","preventionTips":["Run the availability check at startup, not deep inside download completion","Ship ffmpeg with the installer or provide a settings field for its path","Detect GUI-vs-shell PATH differences during onboarding"],"tags":["ffmpeg","missing-dependency","availability-check","path"],"backgroundTag":"missing-dependency","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"}