Turn a folder (or zip) of transparent PNG frames into a WebM, MOV, GIF or MP4, with the transparency intact.
Exported an animation from Blender, After Effects, a canvas or an AI tool as a PNG sequence and need it on a website, in a video editor or in a chat? One command:
aether-renderer-core -i frames/ -o animation.webmProject page · Download · GUI app · Changelog
- 🫧 Transparent output in WebM (VP9), MOV (ProRes 4444) and GIF; MP4 for when you don't need alpha
- 📦 Frames from a folder or a ZIP (macOS
__MACOSX/._files are skipped) - 🔢 Frames in natural order:
frame_2.pngcomes beforeframe_10.png, with or without zero padding - 🌗 Fade in / fade out that fades to transparent, not to black
- 🎛️ Options on the command line, in a JSON or TOML config, or both (the command line wins)
- 🖼️ Preview a single frame without rendering
- 💻 macOS, Linux and Windows, with prebuilt binaries
- 🦀 Also a Rust library: the Aether Renderer GUI is built on it
| Format | Transparency | Best for |
|---|---|---|
webm (default) |
✅ | Websites (Chrome, Firefox, Edge), small files |
mov |
✅ full quality | Video editors: Premiere, DaVinci Resolve, Final Cut, After Effects |
gif |
✅ on/off per pixel | Chat, email, README files, anywhere video isn't allowed |
mp4 |
❌ | Everything else, social media, maximum compatibility |
The format is taken from the output file name (-o loop.gif renders a GIF), or set it with --format.
Safari does not play transparent WebM. For transparent video on Safari, use a GIF, or serve a HEVC-with-alpha version next to the WebM (on the roadmap).
You need ffmpeg on your PATH:
brew install ffmpeg # macOS
sudo apt install ffmpeg # Ubuntu / Debian
winget install Gyan.FFmpeg # WindowsThen either download a binary from Releases (macOS Apple Silicon and Intel, Linux, Windows), or install with Cargo:
cargo install aether-renderer-core# 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
# higher quality WebM (lower crf = better, default 30)
aether-renderer-core -i frames/ -o out.webm --crf 20
# only some files, or a numbered sequence
aether-renderer-core -i renders/ -o scene1.webm --file-pattern 'scene1_*.png'
aether-renderer-core -i renders/ -o out.webm --file-pattern 'frame_%04d.png'
# check a frame first: saves the middle frame (or frame 12) as out.png
aether-renderer-core -i frames/ -o out.webm --preview
aether-renderer-core -i frames/ -o out.webm --preview 12| Option | Default | Description |
|---|---|---|
-i, --input |
required | Folder or .zip with the frames |
-o, --output |
output.<format> |
Output file |
--format |
from the output extension, else webm |
webm, mov, gif or mp4 |
--fps |
30 |
Frames per second |
--file-pattern |
*.png |
Glob (scene_*.png) or numbered sequence (frame_%04d.png) |
--fade-in |
0 |
Seconds to fade in from transparent (from black for mp4) |
--fade-out |
0 |
Seconds to fade out at the end |
--crf |
webm 30, mp4 23 |
Constant quality, lower is better (webm 0–63, mp4 0–51) |
--bitrate |
Target bitrate instead, e.g. 2M (if both are set, --crf wins) |
|
--preview [N] |
Save frame N (default: the middle frame) as a PNG instead of rendering |
|
--open |
Open the result when done | |
-c, --config |
JSON or TOML config file, see below | |
-v, --verbose |
Details and a progress spinner | |
--verbose-ffmpeg |
Show ffmpeg's own output |
If ffmpeg fails, the error shows ffmpeg's own explanation, and no half-written file is left behind.
Every option can live in a .json or .toml file; anything you also pass on the
command line overrides the file. Handy for keeping a project's settings next to its
frames:
# render.toml
input = "frames"
output = "loop.webm"
fps = 24
fade_in = 0.5
fade_out = 0.5
crf = 24aether-renderer-core --config render.toml
aether-renderer-core --config render.toml --fps 60 -o draft.mov # overrideThe same in JSON: examples/example_config.json. Relative paths are relative to the folder you run the command from.
[dependencies]
aether-renderer-core = "0.5"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(cfg)?;
println!("{}", report.summary());RenderConfig::from_file("render.toml") loads a config file, and
aether_renderer_core::preview_frame extracts a single frame.
cargo test # ffmpeg tests are skipped when ffmpeg is missing
cargo clippy --all-targets -- -D warnings
cargo fmtThe tests render real transparent, odd-sized frames to every format and check the
result with ffprobe: size, frame rate, codec and alpha. CI runs them on Linux, macOS
and Windows.
A single frame duplicated N times, rendered to WebM:
| Frames | Total time (s) | Avg time/frame (ms) |
|---|---|---|
| 1 | 1.17 | 1173.9 |
| 100 | 1.79 | 17.9 |
| 1000 | 13.13 | 13.1 |
| 10000 | 112.07 | 11.2 |
Measured with 0.4 (VP8). 0.5 uses VP9, which in our tests takes about 20% longer and gives files about 40% smaller at better quality.
Prefer drag and drop? The Aether Renderer GUI is a desktop app built on this crate.
Download the installer from the GUI releases.
Try it with sacred-stars.zip:
aether-renderer-core -i sacred-stars.zip -o stars.webm- WebM with alpha, MP4, GIF
- Bitrate / CRF quality control, fades
- Preview a single frame
- GUI version with Tauri
- ProRes 4444 MOV, TOML config, config + CLI override, Windows-safe input (0.5)
- Safari-ready transparent video (HEVC with alpha) and a
--format webthat writes both - Resize and crop (
--width,--height) - Frames from stdin, for piping from canvas and AI tools
Ideas and bug reports are welcome in issues.
MIT. Built and maintained by Mads Paaskesen, Hardcore Websmith at MP-IT, with 💛 from Sacred-AI.
Need custom rendering pipelines, video automation or a Rust/Node.js backend? Get in touch.

