tonhowtf/omniget · error
ffmpeg returned code
Error message
ffmpeg returned code {} What it means
mux_video_audio successfully launched ffmpeg, but the process exited with a non-zero status code. Because stderr and stdout are redirected to null, the actual ffmpeg diagnostic is discarded and only the exit code is reported. Typical causes are invalid input files, mismatched stream parameters for stream copy, or an unwritable output path.
Solutions
- Change output container or re-encode instead of `-c copy` (e.g. use `-c:a aac` when muxing Opus/Vorbis audio into MP4).
- Re-enable stderr capture (`Stdio::piped()` and read it) to see ffmpeg's real error message, since current code nulls it.
- Validate both input files with ffprobe (probe()) before muxing; re-download truncated inputs.
- Check the output path is writable and has enough free disk space; update ffmpeg if the input codec is newer than the binary supports.
Example fix
// before
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.await
.map_err(|e| anyhow!("Failed to run ffmpeg: {}", e))?;
if !status.success() {
return Err(anyhow!("ffmpeg returned code {}", status));
}
// after — capture stderr so the exit code comes with a reason
let out = crate::core::process::command("ffmpeg")
.args(["-y", "-i", &video.to_string_lossy(), "-i", &audio.to_string_lossy(), "-c", "copy", &output.to_string_lossy()])
.stderr(std::process::Stdio::piped())
.output()
.await
.map_err(|e| anyhow!("Failed to run ffmpeg: {}", e))?;
if !out.status.success() {
return Err(anyhow!("ffmpeg returned code {}: {}", out.status, String::from_utf8_lossy(&out.stderr)));
} Defensive patterns
Strategy: fallback
Validate before calling
// Ensure inputs are probeable and compatible before stream-copy mux
let vinfo = probe(video).await?;
let ainfo = probe(audio).await?;
if !vinfo.streams.iter().any(|s| s.codec_type == "video") {
bail!("no video stream in {}", video.display());
}
// Opus/Vorbis audio is not MP4-compatible with -c copy; prefer an .mkv/.webm output or re-encode Try / catch
// Since ffmpeg's stderr is discarded, retry once with re-encode fallback on any exit-code error
match mux_video_audio(&video, &audio, &out).await {
Err(e) if e.to_string().starts_with("ffmpeg returned code") => {
warn!("stream-copy failed ({}), retrying with re-encode", e);
// run ffmpeg with -c:v copy -c:a aac into the same output
}
other => other,
} Prevention
- Probe both inputs with ffprobe and check codec/container compatibility before using `-c copy` (Opus/Vorbis won't copy into MP4).
- Choose an output container (MKV) that accepts virtually any stream copy.
- Patch or wrap the library to capture stderr — a bare exit code with nulled stderr makes diagnosis impossible.
- Only mux fully downloaded (non-.part) files; truncated inputs are a top cause of ffmpeg failures.
When it happens
Trigger: Calling mux_video_audio where ffmpeg itself fails: unreadable/corrupt video or audio input, audio track with a codec incompatible with `-c copy` into the chosen container (e.g. Opus in MP4), output file locked or on a full filesystem, or bad characters/paths passed through.
Common situations: Muxing WebM audio into an .mp4 container with stream copy; downloading a video whose separate audio stream failed mid-way (truncated file); output directory lacks write permission; ffmpeg too old for a codec in the inputs.
Related errors
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/3f83e7e4bbe3a2c9.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/ffmpeg.rs:57
let status = crate::core::process::command("ffmpeg")
.args([
"-y",
"-i",
&video.to_string_lossy(),
"-i",
&audio.to_string_lossy(),
"-c",
"copy",
&output.to_string_lossy(),
])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.await
.map_err(|e| anyhow!("Failed to run ffmpeg: {}", e))?;
if !status.success() {
return Err(anyhow!("ffmpeg returned code {}", status));
}
Ok(())
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConversionOptions {
pub input_path: String,
pub output_path: String,
pub video_codec: Option<String>,
pub audio_codec: Option<String>,
pub resolution: Option<String>,
pub video_bitrate: Option<String>,
pub audio_bitrate: Option<String>,
pub sample_rate: Option<u32>,
pub fps: Option<f64>,
pub trim_start: Option<String>,
pub trim_end: Option<String>,View on GitHub (pinned to 8600b91f42)