tonhowtf/omniget · error · anyhow::Error

ffmpeg

Error message

ffmpeg: {}

What it means

start() wraps the ffmpeg child process spawn failure with the message 'ffmpeg: {}'. It fires when std::process::Command::spawn() cannot launch the resolved ffmpeg binary, and the underlying io::Error (e.g. NotFound, PermissionDenied) is interpolated into the message.

Solutions

  1. Verify the ffmpeg path returned by dependencies::ensure_ffmpeg() exists and is executable; re-run the dependency install if not.
  2. Re-install or re-download ffmpeg (e.g. re-run the app's dependency setup) and retry.
  3. Check that no antivirus/permission policy is blocking execution of the ffmpeg binary.
  4. Test the binary manually: run '<ffmpeg-path> -version' in a shell.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// check ffmpeg before calling start
if !ffmpeg_path.exists() {
    // trigger dependency install flow first
}

Try / catch

match dictation::start(progress).await {
    Err(e) if e.to_string().starts_with("ffmpeg:") => reinstall_ffmpeg().await?,
    other => other?,
}

Prevention

When it happens

Trigger: cmd.spawn() returns Err — typically because the ffmpeg path is invalid, the binary lacks execute permission, or the system cannot fork/exec.

Common situations: ensure_ffmpeg() returned a stale or broken path; user deleted/moved the bundled or downloaded ffmpeg; antivirus or sandbox blocks execution; PATH changed since dependency check.

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/1c596b87a95be353. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/dictation.rs:251

pub async fn start(progress: super::ProgressFn) -> anyhow::Result<()> {
    {
        let rec = REC.lock().unwrap_or_else(|e| e.into_inner());
        if rec.is_some() {
            return Err(anyhow!("ja esta gravando"));
        }
    }
    let ffmpeg = crate::core::dependencies::ensure_ffmpeg().await?;
    let opts = options();
    let wav = super::temp_dir().join(format!("dictation-{}.wav", uuid::Uuid::new_v4()));
    let mut cmd = crate::core::process::command(&ffmpeg);
    cmd.args(["-y", "-hide_banner", "-loglevel", "error"]);
    cmd.args(input_args(&opts.device));
    cmd.args(["-ac", "1", "-ar", "16000", "-c:a", "pcm_s16le"])
        .arg(&wav);
    cmd.stdin(std::process::Stdio::piped())
        .stdout(std::process::Stdio::null())
        .stderr(std::process::Stdio::piped());
    let child = cmd.spawn().map_err(|e| anyhow!("ffmpeg: {}", e))?;
    *REC.lock().unwrap_or_else(|e| e.into_inner()) = Some(Recording {
        child,
        wav,
        started: Instant::now(),
    });
    set_phase("recording");
    *LAST.lock().unwrap_or_else(|e| e.into_inner()) = None;
    super::report(&progress, "dictation", "recording", 0, None, None);
    Ok(())
}

/// Para a gravação, transcreve e entrega o texto. Devolve o texto.
pub async fn stop(progress: super::ProgressFn) -> anyhow::Result<String> {
    let rec = REC.lock().unwrap_or_else(|e| e.into_inner()).take();
    let Some(mut rec) = rec else {
        return Err(anyhow!("nao esta gravando"));
    };
    set_phase("transcribing");

View on GitHub (pinned to 8600b91f42)