Aether Renderer

CLI · Rust crate · v0.7.0

aether-renderer-core

PNG frames in, transparent video out. A folder, a ZIP or a stream on stdin becomes WebM, MOV, GIF or MP4, with the alpha intact, fades that go to transparent, and real progress.

crates.io versiondownloadsdocs.rs

Install

You need FFmpeg on your PATH:

brew install ffmpeg            # macOS
sudo apt install ffmpeg        # Ubuntu / Debian
winget install Gyan.FFmpeg     # Windows

Then install with Cargo, or download a binary:

cargo install aether-renderer-core

Usage

# folder of PNGs -> transparent WebM at 30 fps
aether-renderer-core -i frames/ -o out.webm

# from a zip, as a GIF at 24 fps
aether-renderer-core -i frames.zip -o out.gif --fps 24

# for a video editor, with a soft 1 second fade in and out
aether-renderer-core -i frames/ -o out.mov --fade-in 1 --fade-out 1

# MP4 on the colour of the page it will sit on
aether-renderer-core -i frames/ -o out.mp4 --background '#1e1e1e'

# check a frame first: saves the middle frame as out.png
aether-renderer-core -i frames/ -o out.webm --preview

# PNG files back to back on stdin, straight from capture
aether-renderer-capture -i anim.html --stdout -d 4 | aether-renderer-core -i - -o out.webm --frames 120

Which format?

FormatTransparencyBest for
webm✅Websites (Chrome, Firefox, Edge), small files. The default.
mov✅ full qualityVideo editors: Premiere, DaVinci Resolve, Final Cut, After Effects
gif✅ on/off per pixelChat, email, README files, anywhere video isn’t allowed
mp4❌Social media and maximum compatibility

The format follows the output file name, or set it with --format. Safari doesn't play transparent WebM; use GIF there, or MP4 on a matching --background.

All options

OptionDefaultWhat it does
-i, --inputrequiredFolder or .zip with the frames, or - for a PNG stream on stdin
--framesWith -i -: how many frames the stream has (real progress; needed for --fade-out)
-o, --outputoutput.<format>Output file
--formatfrom the extension, else webmwebm, mov, gif or mp4
--fps30Frames per second
--file-pattern*.pngGlob (scene_*.png) or numbered sequence (frame_%04d.png)
--backgroundtransparent (black for mp4)Solid colour behind the frames: '#1e1e1e', white, transparent
--fade-in / --fade-out0Seconds to fade from / to transparent (or the background colour)
--crfwebm 30, mp4 23Constant quality, lower is better
--bitrateTarget bitrate instead, e.g. 2M (--crf wins if both are set)
--preview [N]Save frame N (default: the middle one) as a PNG instead of rendering
-c, --configJSON or TOML config file (the command line wins)
--progress jsonOne JSON object per line on stdout, for GUIs and scripts
-v, --verboseDetails and a progress bar

Progress for other programs

With --progress json, every line on stdout is a JSON object, so a GUI or script can draw its own bar:

{"event":"progress","frame":0,"total_frames":360,"percent":0.0}
{"event":"progress","frame":96,"total_frames":360,"percent":26.67}
{"event":"progress","frame":360,"total_frames":360,"percent":100.0}

As a library

[dependencies]
aether-renderer-core = "0.7"
use aether_renderer_core::config::PartialConfig;

let cfg = PartialConfig {
    input: Some("frames".into()),
    output: Some("out.webm".into()),
    fps: Some(24),
    ..Default::default()
}
.into_config()?;

let report = aether_renderer_core::render_with_progress(cfg, |p| {
    println!("{:.0}% ({}/{} frames)", p.percent, p.frame, p.total_frames);
})?;
println!("{}", report.summary());

render_stream renders PNG files from any reader (no temp files), which is how the desktop app encodes a capture. Full API on docs.rs.

Source on GitHub · Changelog · Next: capture →