# caery-lib
`caery-lib` is the reusable media conversion engine used by [Caery](https://github.com/Tknott95/KnottConverter). It is designed for desktop applications that need to validate, start, monitor, and cancel `ffmpeg` conversions without blocking their UI thread.
The crate supports video-to-audio extraction, video transcoding, and audio transcoding across Caery's supported formats and quality presets.
## Add The Crate
```toml
[dependencies]
caery-lib = "0.1"
```
## File Manager Integration
`request_from_paths` infers the route and output format using extensions only, so it is safe to call while building a context menu. `spawn_conversion` returns immediately; validation, duration probing, and process startup happen on its worker thread.
```no_run
use caery_lib::{
request_from_paths, spawn_conversion, ConversionEvent, ConversionOutcome, QualityPreset,
};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut request = request_from_paths("clip.mkv", "clip.webm")?;
request.quality = QualityPreset::Archive;
let job = spawn_conversion(request);
loop {
match job.recv()? {
ConversionEvent::Progress {
current_seconds,
total_seconds,
..
} => match total_seconds {
Some(total) => println!("{current_seconds:.1} / {total:.1}"),
None => println!("{current_seconds:.1} seconds converted"),
},
ConversionEvent::Log(line) => eprintln!("ffmpeg: {line}"),
ConversionEvent::Finished(outcome) => {
match outcome {
ConversionOutcome::Succeeded => println!("conversion complete"),
ConversionOutcome::Cancelled => println!("conversion cancelled"),
ConversionOutcome::Failed(error) => return Err(error.into()),
_ => {}
}
break;
}
_ => {}
}
}
# Ok(())
# }
```
Poll `ConversionJob::try_recv` from an event loop instead of calling `recv` on a UI thread. Call `ConversionJob::cancel` when the user cancels. Cancellation is idempotent, and dropping the job also requests cancellation so an abandoned UI item does not leave `ffmpeg` running.
A successful `Finished` event is the point at which the caller should refresh or reveal the output. Failed or cancelled `ffmpeg` runs can leave an incomplete output, especially when overwrite was enabled, so callers should not treat file creation alone as success.
## Route Inference
The inference helpers do not read files or inspect streams:
- Audio input plus audio output selects audio transcoding.
- Video input plus audio output selects audio extraction.
- Video input plus video output selects video transcoding.
- Audio input plus video output is rejected.
`audio_format_from_path`, `video_format_from_path`, and `infer_route` are available when an application needs to populate its own menus before creating a request.
## Tool Checks
`check_tools` reports whether `ffmpeg` and `ffprobe` can start. The check is synchronous and timeout-bounded, so run it during application startup or on a background thread rather than in a render callback. `ffmpeg` is required. Missing `ffprobe` removes the total duration; a slow probe delays conversion until the configurable probe timeout, then conversion starts without a total and still reports elapsed output time.
Use `Converter::with_programs` when an application bundles the executables or stores them outside `PATH`. `Converter` also exposes configurable probe and tool-check timeouts.
## Lower-Level API
`build_command`, `validate_request`, `probe_duration`, `start_operation`, and `start_conversion` remain available for applications that need the original command/event API. New embedded integrations should prefer `Converter::spawn` or `spawn_conversion` for cancellation, non-blocking setup, optional-duration progress, and lossless filesystem path handling.
## Requirements
`ffmpeg` performs conversions and `ffprobe` provides duration information. The default `Converter` resolves both executables from `PATH` at runtime.