Hybrid
hybrid Medium — a normal phone is fineA real photograph wearing a living face — eyes, lashes and mouth are drawn on top every frame and are never baked into the picture.
A photo <img> under a transparent 2D canvas. The photo supplies the person; the canvas supplies the life.
What it can express
- The deepest feature rack of any engine here — brows, lids, lashes, eyes, pupils, lips, teeth, tongue, nose, blush, wrinkles — plus glasses, hats, flowers, earrings and neckwear as real drawn accessories
- 25 moods with real per-mood recipes — not a two-scalar fold — a full expression engine with 32 distinct channel recipes, one per mood, each specifying brow, furrow, lid, mouth curve, lip press, gaze, pupil and blush
- Nine timed gesture actions — wink, tongue, brow-raise, nod, frown, stare, whistle, chew and breathe — one-shot performances that ride over the held mood
- It can wink — the expression engine exposes a per-side wink channel through the narrow bridge into the painter — the one thing SVG structurally cannot do
- Swap the person at runtime — a new base photo, its zones and its whole palette can be dropped in mid-session without remounting — this is how a sealed package arrives wearing someone's own face
- Accepts a photo embedded in the package — a base can travel as a data: URI inside the .alive.json, or as a same-origin path — nothing else is accepted
- Features land on the real face, not the box — the paint rectangle is recomputed from where the contained photo actually sits, so a non-square portrait does not shift every feature
- Two painter geometries — 'hybrid' overlays features on a photo; 'sem' switches to the mesh face — the saved style is part of the look
- Five placement numbers — cx, eyeY, mouthY, spread and scale position the whole face on the photo — the same five numbers the 3D engine uses
Moods: 25 protocol moods, each with its own channel recipe — the richest mood support of the five 2D engines — plus nine timed gesture actions. One mood is held at a time; a one-shot gesture never clears it.
What it costs a device
| measured on this box | 375×667 | 1440×900 |
|---|---|---|
| cold mount → first frame | 636 ms | 394 ms |
| rAF fps — idle | 59 | 57 |
| rAF fps — speaking | 59 | 56 |
| CPU cores busy — idle | 0.38 | 0.75 |
| CPU cores busy — speaking | 0.40 | 0.77 |
| worst frame gap (p95) | 16.8 ms | 16.8 ms |
| over the wire | 1.85 MB | 1.85 MB |
| JS heap | 10 MB | 10 MB |
Compute sits between Sketch and SVG (0.38 / 0.75 cores against a 0.08 / 0.10 empty page), but the bandwidth is the real story: 1.85 MB, because a photo base must ship. The measured base here was 1.66 MB on its own.
Why medium: The compute sits mid-pack; the photograph is the real cost. On a phone this engine is expensive in bandwidth and memory before it is expensive in CPU.
Dials it really exposes today
Try it
/avatar-lab/hybrid/
Universal Stage — Hybrid beside the other fouropen/alive-site/universal-stage.html
Honest limits
- Someone has to supply a photo, and photos are heavy. The measured base here is 1.66 MB, and the whole page came to 1.85 MB — six times the payload of the photo-free 2D engines.
- The base must be a BLANK face — no eyes, no lashes, no mouth in the photograph. Feed it an ordinary portrait and you get drawn features on top of real ones.
- No seal/export door on the Universal Stage. SVG, Sketch and Kinetic can be sealed there; Hybrid cannot — its look travels only through the base-swap path.
- The 172 dials are not exposed as a UI on the shipping mount. They are an API surface reached through a package drop or a host page; the deep authoring UI lives on separate lab pages.
- The Hybrid Overlay Lab is a different, older experiment from the shipping mount — it paints ASCII or sketch features over a photo. Do not read its look onto this card.
- Keeps animating when scrolled off-screen. Only the SVG engine pauses on offscreen/hidden; the shared frame driver re-arms its rAF loop unconditionally, so a card scrolled out of view still costs what the table says.
Numbers are software-renderer numbers. Measured 2026-08-04 on the estate box
(18 vCPU, load 2.8–5.3 during the run) under chromium_headless_shell-1232 + SwiftShader, 3 runs per cell, median reported.
SwiftShader rasterizes on the CPU, so a real phone GPU changes the picture — most of all for 3D.
Read the ordering between engines, not the absolute figures.
Evidence for every claim: CARD-FACTS.md. Harness: work/measure-engines.mjs.