Export to After Effects#
Sometimes the people finishing a video are professional motion designers, and they want to work where they're fastest: After Effects. Clipkit exports straight to it.
So you have two ways to finish a video:
- In your product. Use the Clipkit editor for motion design inside your app, with no handoff.
- In After Effects. Export the same video as an editable AE project and hand it to your professional editors.
The export isn't a rendered clip. It's a real project: comps, shape and text layers, keyframes with the same easing, live expressions, footage, cameras and effects. A designer opens it and keeps working.
Across 17 production videos (3–44 s, up to 485 elements, covering UI mocks, glows, particles and 3D cameras), the After Effects render matches the Clipkit render at a 92% mean pixel match.
Run it#
npm i -g @clipkit/ae-exporter clipkit-ae video.json --out ./video-ae
Then in After Effects (2024 or newer): File ▸ Scripts ▸ Run Script File… and pick video-ae/build.jsx. The project builds in a few seconds with the main comp open.
Install the fonts first. REPORT.md lists the fonts the video uses, and assets/fonts/ holds any the video embeds. After Effects silently substitutes a missing font.
On a Mac with After Effects installed, add --aep and the exporter does the rest: it launches AE, builds the project and saves video-ae/<name>.aep.
The output folder:
| file | what it is |
|---|---|
build.jsx | the script you run in After Effects |
build.json | the project description the script executes |
run.jsx | headless variant: builds, saves the .aep, logs instead of showing dialogs |
assets/ | media, pre-rendered sequences, and fonts/ to install first |
REPORT.md | how each element was translated, and the fonts it needs |
The package is @clipkit/ae-exporter on npm. The reverse direction, AE to Clipkit, is @clipkit/ae-importer.
Fidelity rungs#
Every element lands on exactly one rung, and REPORT.md lists them worst-first:
- native — AE has the construct (shape layers, text, footage, precomps, keyframes with temporal ease, time remap, blend modes, Gaussian blur, levels…).
- rewrite — the same result through a standard AE idiom (an expression for plain-group opacity, a track matte for a mask, separate position dimensions, expressions that read the footage size for
fit/crop). - bake — the animation sampled per frame from the Clipkit runtime into dense keyframes (springs, elastic and bounce easings,
noise/wiggleexpressions, staggered channels). Exact, less editable. - prerender — rendered by the Clipkit runtime to a transparent PNG sequence and placed as footage (particles, pixel shaders, ascii, refractive glass), or, for gradient-filled shapes, to a single sprite at the element's peak on-screen size that keeps every transform, filter and effect native (AE cannot set gradient stops from a script).
- approx — a native construct that looks slightly different (halftone, fractal noise, text animators, lights/materials).
- drop — omitted, with the reason.
Native keyframes are verified against the runtime before they are trusted: if the AE keys would not reproduce Clipkit's motion within tolerance, the channel bakes instead.
Flags#
| flag | default | effect |
|---|---|---|
--prefer editable|exact | editable | exact bakes or pre-renders anything that is not bit-equivalent (approximated easings, lit materials, halftone…) |
--ae-version N | 24 | gates per-character text styles and Advanced 3D materials (AE 2024+) |
--backdrop isolate|flatten | isolate | pre-rendered backdrop readers (refractive glass, shaders) see nothing beneath them, or bake the layers beneath into their clip |
--no-prerender | skip the headless-Chrome pass (sequences are left missing; AE warns) | |
--aep | macOS: launch After Effects, build, save <name>.aep (needs AE installed; nothing else open with unsaved changes) |
Pre-rendering needs playwright and Google Chrome, like clipkit render --local.
What maps how#
| Clipkit | After Effects |
|---|---|
shape primitives, paths, trim_*, path morphs | shape layers, Trim Paths, path keyframes |
text, spans, text_shadow, background_color, linear-wipe mask, text-* presets | text layer (box or point), character ranges, stacked Drop Shadow effects, a sourceRectAtTime background shape, Linear Wipe, animators with expression selectors |
glow, drop_shadow, stroke effects, shape shadow | a tinted blurred clone beneath the layer (the runtime's own glow model), the Drop Shadow effect, a Stroke layer style (AE cannot add layer styles from a script, so glow and shadow avoid them) |
shape gradient, path gradients | one runtime-rendered sprite on a footage layer (scaled by expression when the box animates) |
image / video / audio, fit, crop_*, trim / rate / loop / time_remap, volume + fades | footage, anchor/scale/mask expressions (or literals when sizes are known), Time Remap, Audio Levels |
| plain group | null parent (+ opacity expression on children) |
clip / mask / time_remap / filters / effects on a group | precomp (+ track matte, rounded clip mask, Time Remap), built larger when the group scales up |
keyframe_animations, presets, loops, motion paths | keyframes with exact temporal ease, spatial keys with tangents and auto-orient |
deterministic expr | live AE expression |
3D fields, camera, lights, material, bloom, motion_blur | 3D layers (z and x/y rotation sign-flipped for AE's axis), one-node camera, Advanced 3D lights/materials, a Glow adjustment layer, comp motion blur |
| captions | hold-keyed Source Text per chunk + a Fill Color animator on the active word |
How we measured#
We exported 17 real clipkit.dev videos, built each one in After Effects 2026, and rendered 16 evenly spaced frames per video. Each frame was compared with the same frame of the Clipkit render. A pixel counts as a match when every channel is within 13/255, at half resolution after a 1 px blur, so sub-pixel anti-aliasing doesn't count against it.
| pixel match | SSIM | |
|---|---|---|
| mean | 92.3% | 0.938 |
| median | 93.8% | 0.935 |
| worst video | 80.2% | 0.885 |
Most of what remains is text placement: without font metrics at export time, widths and baselines of text without a set width are estimated. Glyph rendering also differs slightly between Chrome and After Effects.
A few things need a look once the project is open: gradient strokes on vector paths with animated trims (the stops stay at AE's default), LUT files (load them by hand), and fonts.