tonhowtf/omniget · error

ffmpeg

Error message

ffmpeg: {}

What it means

start() spawns the ffmpeg child process via crate::core::process::command(). If the OS-level spawn fails (io::Error), it is wrapped as "ffmpeg: {io error}". This happens before any recording state is stored.

Solutions

  1. Ensure ensure_ffmpeg().await? is awaited successfully before start() and that ffmpeg exists at the returned path
  2. Run `ffmpeg -version` manually with the same environment/PATH to reproduce the spawn failure
  3. Check file permissions on the ffmpeg binary (chmod +x)
  4. Check system resource limits (ulimit, disk space) if the binary exists

Example fix

// before
start(opts).await?; // assumes ffmpeg is present
// after
let ffmpeg = ensure_ffmpeg().await?; // surface install errors early
println!("using ffmpeg at {}", ffmpeg);
start(opts).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

let ffmpeg = ensure_ffmpeg().await?;
if !std::path::Path::new(&ffmpeg).exists() {
    return Err(anyhow!("ffmpeg missing at {}", ffmpeg));
}

Try / catch

match screen_record::start(opts).await {
    Err(e) if e.to_string().starts_with("ffmpeg:") => {
        eprintln!("failed to spawn ffmpeg: {} — reinstall via ensure_ffmpeg()", e);
        ensure_ffmpeg().await?;
        screen_record::start(opts).await
    }
    other => other,
}

Prevention

When it happens

Trigger: The ffmpeg binary path is invalid or not executable, the binary was removed after ensure_ffmpeg() earlier, resource limits (fork/ENOMEM), or an invalid working directory for the child.

Common situations: ffmpeg not installed and ensure_ffmpeg skipped or failed silently; a broken PATH; permission bits stripped from the binary; disk-full or fd-limit conditions.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/screen_record.rs:364

        PathBuf::from(opts.output_dir.trim())
    };
    std::fs::create_dir_all(&dir)?;
    let ring = opts.replay_seconds > 0;
    let (target, ring_dir, output) = if ring {
        let r = super::temp_dir().join(format!("replay-{}", uuid::Uuid::new_v4()));
        std::fs::create_dir_all(&r)?;
        (r.clone(), Some(r), None)
    } else {
        let out = dir.join(format!("Gravacao {}.mp4", stamp()));
        (out.clone(), None, Some(out))
    };
    let args = build_args(&opts, &target, ring);
    let mut cmd = crate::core::process::command(&ffmpeg);
    cmd.args(&args)
        .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))?;
    *ERROR.lock().unwrap_or_else(|e| e.into_inner()) = None;
    *SESSION.lock().unwrap_or_else(|e| e.into_inner()) = Some(Session {
        child,
        started: Instant::now(),
        output,
        ring_dir,
        opts,
    });
    // Se o ffmpeg morrer nos primeiros instantes (permissão, dispositivo), avisa.
    tokio::time::sleep(std::time::Duration::from_millis(900)).await;
    let died = {
        let mut s = SESSION.lock().unwrap_or_else(|e| e.into_inner());
        match s.as_mut() {
            Some(sess) => match sess.child.try_wait() {
                Ok(Some(_)) => Some(sess.child.stderr.take()),
                _ => None,
            },
            None => None,

View on GitHub (pinned to 8600b91f42)