← Topper Bowers

FX Lab · Round 1

EXPOSURE Screenings

One 12-second motion brief built in each tool, and one grain test on real Loom footage. The question is how well an agent can drive each tool, and why our film grain has looked bad.

Run 2026-10-07Driver Claudespace-bunny's one EXPOSURE run (Tesseract) is on the Round 2 page

The verdicts

Best control

EffectCraft

After Effects clone with a CLI. Every beat and the film finish, built inside the tool.

Best loop

HyperFrames

Lint and snapshots are fast, but the page can't read its own pixels, so halation is faked.

Not viable here

Natron

x86 only. One frame took 4 minutes under Rosetta.

Grain fix

Grain at 1080p

Grain at output resolution, weighted to the midtones, encoded with -tune grain.

Study 1

EXPOSURE, 12 s

The same brief for every tool: 1920×1080, 24 fps, 288 frames. These are web copies at 6.5 Mbps.

EffectCraft 0.3.1

All 8 beats done

5 builds · full render in 34 s · a check frame in ~130 ms. Text animators with an expression selector, precomps for the RGB split, Add Grain, Lumetri. Two snags: gradients can't be set from a script, and keyframes snap to whole frames.

HyperFrames 0.8.127

All beats; tracking approximated

3 check runs · full render in 24 s. GSAP stagger, a clip-path gate, seeded per-frame grain on canvas. Lint forbids animating letter spacing, and halation is a blurred copy of the title.

EffectCraft check frames at 1, 2.2, 3.8, 5.5, 7.4, 9.5 and 11.2 seconds
EffectCraft, first-pass check frames (the halation was too strong, and was toned down later)
HyperFrames check frames at the same seven times
HyperFrames, check frames at the same times

The brief

TimeBeatEffectCraftHyperFrames
0–1.5 sDust motes drift in black60 shapes with wiggle expressionsSeeded canvas
1.5–3 s2 px line draws out, with bloomScale keys + stacked GlowscaleX + box-shadow
3–4.5 sGate opens to 2.39:1Keyed rect + radial gradientclip-path tween
4.2–6.5 sLetters build in, tracking tightensExpression selector on textIndexStagger; glyphs slide in x
6.5–8.5 sLight leak + RGB splitShift Channels ×3, ADD blend3 colored copies, screen blend
8.5–10.5 sSubtitle + underlineDoneDone
10.5–12 sGate closes to a dotDoneDone
FinishHalation, grade, grain, vignetteGlow, Lumetri, Add Grain (luma bands)Faked: blurred title copy, soft-light grain

Tool matrix

Who got a turn

ToolStatusRenderNotes
EffectCraftDone34 sThe most controllable. Its CLI, JSX object model and MCP server all read back every property.
HyperFramesDone24 sToday's default. Weak wherever an effect has to read pixels.
NatronStopped4 min/frameLinear OCIO, SeGrain and Shadertoy are the right ideas, but there's no ARM build. Headless footguns: an injected frame global, Glow won't load, text isn't centered.
FilmCraftFinisher only4.4 s / 5 sPremiere clone, 303 effects, JSONL command runner. Its Noise lifts the blacks.
Diffusion StudioSkipped—Browser canvas only, effects are mostly blur, free tier is watermarked.
Resolve 21 (free)Blocked—No external scripting in the free version.
Osmo film emulationSkipped—Web app and paid plugins. No CLI or API.
Natron test still at 5.5 seconds: title off-center to the right, subtitle showing too early
Natron's only still (5.5 s). It took 4 min 07 s to render, with the title off-center and the subtitle showing too early.

Study 2

Grain bake-off

5 s from close-quarters, upscaled and graded to 1080p. Each tool added only the grain, then every result went through our 12 Mbps share encode. Shown at 100%.

Top left: today's look.sh · Top right: fixed ffmpeg grain · Bottom left: FilmCraft Noise · Bottom right: AV1 grain synthesis at 3 Mbps
VariantMasterMid σ · masterafter 12 Mbpsafter 6 MbpsShadow / midBlack lift
G0 today's look.sh22.8 MB4.734.914.510.52−0.54
G1 fixed ffmpeg89.7 MB5.285.244.520.35−0.22
G3 FilmCraft Noise93.1 MB5.115.064.470.70+1.65
G4 AV1 grain synthesis——3.46 at 1.9 MB (3 Mbps)0.36−0.38
G2 EffectCraft Add Grain56.0 MBCouldn't be measured: with no effect applied, EffectCraft's own passthrough already changes the plate by σ 10.6.
G5 Natron SeGrain—Couldn't be measured: Natron's video reader returned 251 frames at the wrong width for a 120-frame clip.

σ is grain strength in 8-bit code values, measured on a high-passed difference from the plate. Shadow/mid: real film grain fades in the shadows, so lower is more film-like. Black lift: mean change in pure black.

Why our grain has looked bad

  1. Wrong resolution. look.sh adds 1-pixel noise at H3's 1344×768. When the film plays at 1080p, the grain is blown up into soft blotches.
  2. Same strength everywhere. It adds as much noise in the shadows as in the midtones. Real film grain fades in the shadows.
  3. Grain eats the bitrate. The grained HyperFrames render was 75 MB against 3 MB clean at the same quality, so any re-encode that caps bitrate starves it.
  4. The registry overlay loops. HyperFrames' grain-overlay is one texture cycled 20 times a second, laid on top in normal blend, so it lifts the blacks.

Recommended: use the G1 recipe, run it after upscaling to 1080p, and always encode with -tune grain. AV1 grain synthesis keeps grain at a quarter of the bits, but the player has to draw it, so check Safari and iOS first.

Next round

Other headless tools to try