lottie-doctor
v0.2.0
Published
Diagnose and repair broken Lottie files. Fixes garbled CJK/Unicode text (NFD→NFC) that other optimizers ignore, plus size optimization. CLI + library + GitHub Action.
Maintainers
Readme
lottie-doctor 🩺
Diagnose and repair broken Lottie files — not just shrink them.
Every other Lottie tool only makes files smaller. lottie-doctor is the only
one that also fixes them: it repairs corrupted CJK/accented text — including
double-encoded "mojibake" (UTF-8 bytes misread as Latin-1 and re-saved) and
Unicode decomposition (NFD) — the classic bugs you get when a designer exports
Korean/Japanese layer names from After Effects on macOS.
Real example from a shipping app: a character layer named
손("hand") was stored in the JSON as4áá©á«— completely corrupted.lottie-doctorrecovers it to4손. NFC-only optimizers can't: the text isn't decomposed, it's byte-level mangled.
npx lottie-doctor check animation.json
npx lottie-doctor fix animation.jsonWhy this exists
Lottie JSON exported from After Effects is routinely broken in two ways:
- Corrupted text. Two failure modes, both passing as "valid UTF-8" so every
optimizer ignores them:
- Mojibake (double-encoding): the bytes of
손get misread as Latin-1 and re-saved, becomingáá©á«. Recoverable by re-interpreting the bytes. - Decomposition (NFD):
온보딩is stored as separate jamo (ㅇㅗㄴㅂㅗㄷㅣㅇ) that render broken. Recoverable via NFC. Existing tools (lottie-optim, TinyLottie, Lottiemizer, …) do nothing about either.
- Mojibake (double-encoding): the bytes of
- Bloat. 15-digit float spam and raster PNGs base64-encoded inside the "vector" JSON, easily pushing a single mascot animation past 1 MB.
lottie-doctor does the lossless text repair first (mojibake → NFC), then
optionally trims the bloat.
Mojibake repair is deliberately conservative — it only fires when a string
carries an unambiguous corruption signature (C1 control bytes) and re-decodes
cleanly, so legitimate accented text like café is never touched.
What it does
| Check | lottie-doctor | typical optimizers |
| --- | :---: | :---: |
| Repair double-encoded text (mojibake) | ✅ | ❌ |
| Repair decomposed Unicode (NFD → NFC) | ✅ | ❌ |
| Works on .lottie (dotLottie ZIP) archives | ✅ | partial |
| Detect embedded raster images | ✅ | partial |
| Round float precision | ✅ (opt-in) | ✅ |
| Strip editor-only metadata | ✅ (opt-in) | ✅ |
| Fail CI on unhealthy files | ✅ | ❌ |
CLI
# Diagnose (exits 1 if anything is wrong — drop it straight into CI)
lottie-doctor check src/assets/*.json --max-size 500
# Repair text (mojibake + NFC, safe & lossless) → animation.fixed.json
lottie-doctor fix animation.json
# Repair + shrink, overwriting in place
lottie-doctor fix animation.json --write --precision 3 --strip-meta
# Works on dotLottie ZIP archives too → animation.fixed.lottie
lottie-doctor fix animation.lottieBoth commands accept raw .json and .lottie (dotLottie ZIP) files. For
.lottie, every packed animation is repaired and the archive is repacked with
all other entries (manifest, images, themes) preserved byte-for-byte.
check output
temi_large.json 15.3 KB
✖ encoding 25 double-encoded string(s) (mojibake) — corrupted text
e.g. "4áá©á«" → "4손"
⚠ precision 68 number(s) over 3 decimals — try fix --precision 3
→ run: lottie-doctor fix temi_large.jsonLibrary
import { analyze, fix } from "lottie-doctor";
const report = analyze(jsonString);
if (report.encoding.nonNfc > 0) {
const { data } = fix(jsonString); // NFC repair, returns a clean copy
}fix() never mutates your input and is idempotent. Text repair (mojibake + NFC)
is on by default; precision and stripMeta are opt-in.
For dotLottie archives, use the byte-oriented variants:
import { analyzeDotLottie, fixDotLottie } from "lottie-doctor";
const bytes = new Uint8Array(await file.arrayBuffer());
const { data } = fixDotLottie(bytes); // returns repacked .lottie bytesThe library is isomorphic — it runs in Node and the browser (the demo above is the same code, no server).
Roadmap
- [x] GitHub Action (
lottie-doctor/check@v1) for CI - [x]
.lottie(dotLottie ZIP) support - [x] Web playground with before/after preview
- [ ] Embedded-image externalization & re-compression (the big size win)
- [ ] Widen mojibake detection to Latin-1 accents (no C1 signature)
License
MIT
