Determinism
Every animation in Cleya is a pure function of time.
A compiled scene exposes window.CLEYA.seekTo(t). To capture frame n, the renderer seeks to
n / fps and screenshots. Nothing is played in real time, so nothing depends on when a callback
fired or how loaded the machine was.
This is the single constraint that makes everything else work:
- A preview frame is the master's pixels.
--at 3.2renders exactly what second 3.2 of the final file will contain, so an agent can check one frame instead of rendering thirty seconds. - Frames render in parallel. Work is sliced across workers, one Chrome process per worker. Sharing one browser across tabs does not work — background tabs get their animation frames throttled, and unthrottled tabs then contend.
- Regression checks mean something.
diffcompares two renders and reports PSNR. That is only useful because an unchanged scene renders bit-identically.
The one rule when writing raw HTML
CSS @keyframes do not sample. They advance on wall-clock time, so seeking gives you the
same frame over and over — the classic symptom is a "video" that looks like a slideshow.
If you drop to --html, the page must define window.CLEYA.seekTo(t) and move everything from
that function. With --runtime gsap you author a paused timeline and call cleya.scene(tl),
which wires seekTo(t) to tl.time(t) for you.
Readiness
Every capture path awaits window.CLEYA.ready before the first frame — scenes resolve it on
document.fonts.ready, bounded at 15 seconds. Fonts therefore never pop in mid-render.
Render tuning
| Variable | Effect |
|---|---|
CLEYA_RENDER_WORKERS | Override the worker count (defaults to half your cores, capped at 4). |
CLEYA_NO_GPU=1 | Force software rasterisation. GPU is on by default; it is dramatically faster for full-frame filter effects and produces bit-identical output GPU-to-GPU. |
CLEYA_RENDER_ENGINE | chrome (default) or webkit. |
CLEYA_CHROME / CLEYA_CHROME_FLAGS | Point at a specific binary, or pass flags such as --no-sandbox. |