async fn run_ffmpeg_sidecar_unlocked(
app: &AppHandle,
slot: &Arc<FfmpegVideoSlot>,
args: Vec<&str>,
) -> Result<(), String> {
let (mut rx, child) = app
.shell()
.sidecar("ffmpeg")
.map_err(|e| e.to_string())?
.args(args)
.spawn()
.map_err(|e| format!("Failed to start ffmpeg sidecar: {}", e))?;
*slot.child.lock().await = Some(child);
let mut success = false;
while let Some(event) = rx.recv().await {
match event {
CommandEvent::Terminated(payload) => {
success = payload.code == Some(0);
break;
}
CommandEvent::Error(err) => {
*slot.child.lock().await = None;
return Err(format!("ffmpeg sidecar error: {}", err));
}
CommandEvent::Stdout(_) | CommandEvent::Stderr(_) => {}
_ => {}
}
}
*slot.child.lock().await = None;
if success {
Ok(())
} else {
Err("ffmpeg sidecar failed".into())
}
}
Built with
FFmpeg Processing
ffmpeg and ffprobe ship as bundled sidecars for yt-dlp muxing, scrubber sprite sheets, and quiet metadata probes.
yt-dlp invokes ffmpeg when a download needs merge or post-process steps. RuForge watches stdout after the byte bar hits 100% and keeps the queue row in a Processing phase until the child process exits. Audio-only jobs skip video post-process paths.
Scrubber hover previews are local sprite sheets. Settings → Downloads auto scrubber previews (default on) tells downloader.rs to call extract_frames after a successful video finish. The ffmpeg filter chain samples one frame every five seconds into 160×90 tiles on a 10×10 grid (fps=1/5,scale=160:90,tile=10x10). Sheets land under .ruforge/thumbs/ beside the video.
useScrubberThumbs.ts loads sheet paths and maps hover position to a tile. Chapter scrubber and simple scrubber both use the same hook; Generate Previews in the library calls the same Rust command when auto mode is off. Completing a sheet emits scrub-sprites-updated so open players reload without restart.
ffprobe warms a disk cache (ffprobe-hints under app data). The player UI does not show codec strings today. Delete and replace flows cancel in-flight ffmpeg work via the per-file lock so files are not left locked on disk.
In the repo
Where it shows up
- Sidecars
binaries/ffmpeg-*andbinaries/ffprobe-*intauri.conf.json -
src-tauri/src/commands/media.rssprites, posters, ffprobe cache -
useScrubberThumbs.ts,ChapterScrubber.tsx,ScrubHoverPreview.tsx - Settings → Downloads auto-preview toggle (
autoScrubPreviewsin store settings)