rasterlottie
rasterlottie is a pure Rust, headless Lottie rasterizer focused on a validated target corpus.
The immediate target is not full Lottie parity. The target is a deterministic,
server-side renderer that can parse a pragmatic subset of Lottie JSON, explain
why unsupported animations fail, and rasterize supported animations into RGBA
frames. GIF export is available through the default gif feature.
Installation
[]
= "<ver>"
The default feature set enables gif, images, and text.
Enable the optional dotlottie feature when you need to load .lottie archives:
[]
= { = "<ver>", = ["dotlottie"] }
If you only need frame rendering without GIF export, image assets, or text layers:
[]
= { = "<ver>", = false }
Basic usage
use ;
let animation = from_json_str?;
let frame = default.render_frame?;
assert_eq!;
# Ok::
With dotlottie enabled, you can also load a packaged archive:
#
#
#
#
Current status
- Parses a small but useful Lottie subset
- Reports unsupported features through a deterministic support analyzer
- Exposes a rendering API backed by
tiny-skia - Can render static rectangles, rounded rectangles, and ellipses into RGBA frames
- Can render static and basic animated custom bezier shape paths into RGBA frames
- Honors animation and layer frame windows, plus precomp start time and stretch
- Supports scalar time remapping on precomp layers
- Can evaluate basic animated scalar and vector properties over time, including spatial and split position transforms
- Supports linear and radial gradient fills and strokes
- Supports layer masks for
add,subtract,intersect, andnone - Supports alpha and luminance track mattes, including inverted modes
- Supports embedded data URL image assets and image layers when the default
imagesfeature is enabled - Supports external image assets through an explicit resolver API when the default
imagesfeature is enabled - Supports loading
.lottiearchives when the optionaldotlottiefeature is enabled - Supports glyph-backed text layers with stepped document keyframes when the default
textfeature is enabled - Ignores controller-style effects on null layers
- Accepts single-source merge paths that collapse to a no-op
- Includes JSON fixture regressions for gradient and matte semantics under
tests/fixtures - Includes PNG golden image-diff regressions for representative shape fixtures under
tests/image_diff.rs - Validates a small public target corpus under
tests/corpus - Supports layer parenting, stroke dash patterns, trim paths, polystars, and repeaters
- Can encode supported animations into GIF bytes when the default
giffeature is enabled - Supports solid fills and strokes for the current target corpus
Target corpus support profile
The default profile is intentionally strict. It allows:
- shape layers
- precomp layers
- null layers
- common shape item containers and primitives
It currently rejects:
- text animators, text paths, and boxed text
- external image assets without a resolver
- layer effects on rendered layers
- expressions
- non-precomp or non-scalar time remapping
- unsupported gradient encodings or gradient types
- unsupported mask and track matte modes
- unknown shape item kinds
Why start this way
The hardest part of a pure Rust renderer is not drawing a rectangle. The hard part is drawing the right rectangle for the right frame and failing predictably when the animation needs a feature that is not implemented yet.
This project starts by making that contract explicit first.
Validation
tests/image_diff.rscompares representative fixture renders against checked-in PNG goldenstests/corpus.rsvalidates the current public target corpus listed intests/corpus/manifest.jsontests/reference/render_fixture.htmlis the browser-side reference harness used to regenerate PNG goldenscargo run --example rasterlottie_cli -- analyze <input.json>prints the current support reportcargo run --example rasterlottie_cli -- render-gif <input.json> <output.gif>renders a GIF with optional--fps,--duration, and--quantizer-speedwhen the defaultgiffeature is enabledcargo run --example rasterlottie_cli -- render-png <input.json> <output.png>renders a PNG with optional--frame,--background, and--scalecargo run --example rasterlottie_cli -- render-mp4 <input.json> <output.mp4>renders an MP4 with optional--fps,--duration,--background,--scale,--crf,--preset,--codec,--pix-fmt, and--losslesscargo run --example rasterlottie_cli --features dotlottie -- analyze <input.lottie>loads a packaged archive and prints the selected animation's support reportcargo run --example rasterlottie_cli --features dotlottie -- render-gif <input.lottie> <output.gif>renders a GIF from a packaged archivecargo run --example rasterlottie_cli --features dotlottie -- render-png <input.lottie> <output.png>renders a PNG from a packaged archivecargo run --example rasterlottie_cli --features dotlottie -- render-mp4 <input.lottie> <output.mp4>renders an MP4 from a packaged archivecargo run --example benchmark_render -- <input.json> --mode gif --jsonbenchmarks raw frame rendering with the same frame sampling used byrender-gifcargo run --example benchmark_render --features dotlottie -- <input.lottie> --mode gif --jsonbenchmarks packaged archives with the same frame sampling used byrender-giftools/bench/compare-with-rlottie-docker.ps1 -InputJson work\input.json -Mode bothcomparesrasterlottieraw render timing againstrlottieinside Docker
Tracing
rasterlottie can be built with an optional tracing feature for runtime diagnostics.
cargo run --example rasterlottie_cli --features tracing -- analyze <input.json>cargo run --example rasterlottie_cli --features tracing -- render-gif <input.json> <output.gif> --fps 60cargo run --example rasterlottie_cli --features tracing -- render-mp4 <input.json> <output.mp4> --fps 60
Set RASTERLOTTIE_TRACE=1 to enable subscriber initialization in the example CLI.
RUST_LOG=rasterlottie_cli=debugshows top-level CLI spans such asprepare_animation,render_animation,encode_frames,write_output, andwait_ffmpegRUST_LOG=rasterlottie=traceadds renderer internals such asrender_layer_stack,composite_pixmap,apply_track_matte,draw_path,trim_path,fill_path,stroke_path, and GIF-specific spans likeencode_gif_frame
Example:
$env:RASTERLOTTIE_TRACE='1'
$env:RUST_LOG='rasterlottie_cli=debug,rasterlottie=trace'
cargo run --example rasterlottie_cli --features tracing -- render-mp4 work\input.json work\output.mp4 --fps 60
The tracing feature is disabled by default, so normal library consumers do not pay for the subscriber or emit renderer spans unless they opt in.
Next milestones
- Expand the public corpus only when
miq-gen-rstraffic shows a real need - Add broader text support only if the target corpus needs text animators, text paths, or boxed text
- Reassess rendered layer effects, expressions, and richer time-remap cases against real-world inputs
- Add richer frame export helpers for APNG and fixture pipelines
- Expand reference image-diff coverage for gradients, mattes, and any newly supported public corpus samples
License
Licensed under either of the following, at your option:
- MIT
- Apache-2.0