← Topper Bowers

FX Lab · Round 3 · Cut lab

SHIP LOG Screenings

One 20-second edited promo built in four tools, with no 3D. Each agent found its own stock footage and music, cut to the beat, built a lower third and a bar chart of real commit counts, then mixed to −14 LUFS.

Every run was Claude (Opus 5.5), started cold as a subagent with no knowledge of earlier rounds or of the other runs. Videos, check frames, timings, what fought back, and the exact prompts are below.

Every tool finished every beat.Friction is the difference.

1920×1080 · 30 fps · 600 framesFootage Mixkit stockData 12 days of commitsRun 2026-10-10Next: Round 4, REEL

The verdicts

Fastest render

fframes

About 20 ms a frame, with inspect and contact-sheet commands built for an agent. Footage is second-class: in-points, fit, blur and grade all live in one hand-written shader.

Fastest to a cut

EffectCraft

11 minutes and the cleanest grade, because After Effects vocabulary transfers. Font handling is the obvious gap.

Undocumented basics

Tesseract

Did what was asked at a good speed, but clip placement and in-points had to be found by experiment.

Most renders

HyperFrames

Seven renders, most lost to silent audio behaviour. Still the only one with a documented route from footage to mix.

Before you watch

The brief had an error. It asked for a 90 commits callout, but commits.csv sums to 89. All four agents caught it and showed 89.

Same footage pool. All four sourced from Mixkit, and they overlap heavily: the same aerial city shows up in all four, the eye close-up and keyboard in three. This comparison is about tooling more than taste in footage.

At a glance

HyperFrames 0.8.140fframes 1.2.0EffectCraft 0.3.1Tesseract 0.3.1
All 6 beats● done (title on half-beats)● done (open ends 1.83 s at 130 BPM)● done● done (title on 8ths)
Designed transitionsdiagonal wipe + whipclipPath mask wipe + whipwhip with motion blurmatte wipe
MusicMixkit #130, own beat grid at 122 BPM (the tool's beats said 224.7)Mixkit "Cat Walk", 130 BPM grid◐ synthesized at exactly 120 BPM, which skips beat findingMixkit track, librosa beats
SFXnone (source pages blocked)synthesized (sox) whoosh ×2 + hitsynthesized whoosh + hitwhoosh + hit
Loudness / true peak (measured)−13.9 LUFS / −2.4−14.1 / −1.7−14.1 / −1.1−14.2 / −1.9
Full renders7222
Render time per frame52–88 ms~20 ms100–110 ms~50 ms
Wall clock19 min17 min11 min14 min
Master file size21 MB11 MB34 MB19 MB
Biggest frictionaudio: an automation lane silently overrides volume; the true-peak guard silently cut 6–9 dBfootage API: no in-point, fit, blur or grade, so one custom shader does all of itwon't import a .ttf; the Bold style is ignoredvideo draws at native size from the top-left; "cover" fit doesn't fill; 800 KB of schemas

The brief

TimeBeat
0–2 sCold open: one footage shot with a kinetic title, SHIP LOG, built letter by letter on the beat.
2–9 sMontage: at least 6 cuts, every one on a beat, at least one designed transition, and a slow push-in.
~4–8 sLower third: Day 1 → Day 12 with the subtitle creative-loom.
9–15 sData beat: footage drops behind while a bar chart of the commit counts builds, one bar per beat; the tallest bar (34) in the accent colour.
15–18 sPayoff: 3–4 fast cuts, ending on a held shot with a counting-up stat callout.
18–20 sEnd card on #0b0b0f with the wordmark; music resolves by 20.0 s.

HyperFrames 0.8.140

render 31–53 s7 renders19 min
Check frames from the HyperFrames cut at 1, 3, 5.5, 8, 11, 14, 16.5 and 19 seconds
1.0 · 11.03.0 · 14.05.5 · 16.58.0 · 19.0 s

How

  • tools/gen.ts writes index.html from the beat grid, cut list and CSV.
  • 13 clips, two designed transitions, and push-ins on several shots.
  • Frame diffs were used to verify cuts, because the snapshot pass misses grade and timing bugs.

Friction

  • The audio path cost 3 renders. A volume lane overrides data-volume without saying so, and the true-peak guard reacted to a 20 ms AAC blip.
  • The grade isn't applied on a clip's first frame, so each clip starts one frame early, hidden.
  • Rounding times to 4 decimals pushed one cut a frame late.
  • Mixed grade: the whiteboard is bright and the champagne stays golden.

fframes 1.2.0

render 12 s2 renders17 min
Check frames from the fframes cut at the same eight times
1.0 · 11.03.0 · 14.05.5 · 16.58.0 · 19.0 s

How

  • Rust + svgr! scenes on Skia/Metal, with ffmpeg linked in for encoding.
  • One SkSL shader handles reframing, push-in, blur, grade and dimming for every clip.
  • The chart shows every day label dimly from the start and lights each one as its bar lands.

Friction

  • get_synced_video_frame has no source in-point. The agent cloned the frame and changed its index instead.
  • Scenes only cross-fade, so the wipe and whip were built by hand.
  • It wouldn't link on Rust 1.89. The agent installed nightly-2026-04-28 and pinned it in the project.
  • Jost has no → glyph, so the arrow is drawn as a path. The default limiter left the true peak above −1 dBTP.

EffectCraft 0.3.1

render 62–66 s2 renders11 min
Check frames from the EffectCraft cut at the same eight times
1.0 · 11.03.0 · 14.05.5 · 16.58.0 · 19.0 s

How

  • build.jsx builds the whole edit in an After Effects-style object model, saved as study.ecproj.
  • One adjustment layer grades all the footage, which gave the most consistent look of the four.
  • Every detected cut is on a 15-frame beat, apart from the whip, which settles on its beat.

Friction

  • Fonts load only from the system folders. The agent ran the tool with HOME=$PWD/home and put Jost in that folder's Library/Fonts.
  • style = "Bold" is accepted and ignored; the weight works through layer.setText.
  • There are no API docs, so property paths had to be found by probing.
  • The synthesized music made the beat grid trivial. That's legal under the brief, but it dodges the hardest editing task.

Tesseract 0.3.1

render ~30 s2 renders14 min
Check frames from the Tesseract cut at the same eight times
1.0 · 11.03.0 · 14.05.5 · 16.58.0 · 19.0 s

How

  • build.py writes the native document, and the packaged ship-log.tsrct stays editable.
  • A sliding matte with an accent edge and a whoosh reveals the whiteboard shot.
  • The first render landed bars and letters one frame late; the second fixed it.

Friction

  • Video layers draw at their own pixel size from the top-left corner, and "cover" doesn't fill, so each clip was centred and scaled by hand.
  • How a clip's source in-point is stored isn't documented; the agent found it by running a trim on a scratch copy.
  • The two schemas total about 800 KB, and required fields could only be found by grepping them.
  • There are no groups, so the lower third was animated layer by layer.

Inputs

What each agent was told

Verbatim, with local paths shortened. Each run got the same subagent prompt with <tool> filled in, plus the brief and that tool's TOOL.md.

Subagent prompt (every run)
You are an editor and motion designer, working on your own from start to finish with no further input. Read cut-lab/BRIEF.md and cut-lab/runs/<tool>/TOOL.md, then build the piece in cut-lab/runs/<tool>/opus/ and write every deliverable there. Use only the assigned tool for the edit, graphics and mix, as the brief's rules say. Don't read or list anything else under experiments/cut-lab/runs/, and nothing under creative-loom-fx-lab/. Don't use the Creative Loom MCP tools or any paid generation. Make reasonable creative decisions yourself and keep going until out/final.mp4 exists and NOTES.md and SOURCES.md are written. Then reply with a short summary: beats done/approximate/impossible, renders, render time, and the biggest friction.
SHIP LOG brief: BRIEF.md
# SHIP LOG: a 20-second edited promo

You are the editor and motion designer. Cut a 20-second promo about one small software team's two-week sprint, built from real stock footage, a music track, and 2D motion graphics. Build it with the assigned tool (see "Rules"). There is no 3D in this study: it tests cutting footage to music, transitions, kinetic type, a data graphic, lower thirds, and the sound mix.

## Inputs (in `cut-lab/assets/`)

- `commits.csv`: 12 days of real commit counts (`day,commits`). Use these values exactly.
- `Jost.ttf`: a geometric sans you may use (or pick a better free font).

Everything else you source yourself:

- **Footage.** Find 6–12 real stock clips under a free license that allows reuse (for example Pexels, Pixabay, Mixkit, Coverr, Wikimedia Commons, or the Internet Archive). Pick shots that tell the story: late-night screens, hands on keyboards, whiteboards, a city at night, coffee, a launch/celebration moment. No AI-generated footage.
- **Music.** One instrumental track, 100–130 BPM, under a free license (or one you synthesize yourself). Find its beats and cut to them.
- Record every source URL and license in `SOURCES.md`.

## Spec

- 1920×1080, 30 fps, exactly 20.0 s (600 frames), stereo AAC music.
- Palette: near-black `#0b0b0f`, warm white `#f5f1e8`, one accent of your choice. Keep the footage graded consistently.

| Time | Beat |
|---|---|
| 0–2 s | Cold open: a single footage shot with a kinetic title, `SHIP LOG`, built letter by letter on the beat. |
| 2–9 s | Montage: at least 6 cuts, every cut on a beat of the music. At least one cut uses a designed transition (a wipe, a match cut, a whip, or a mask reveal), not only hard cuts. Footage is reframed/scaled to fill 16:9 without letterboxing; at least one shot has a slow push-in. |
| ~4–8 s | A lower third slides in over the footage: `Day 1 → Day 12` with a small subtitle, `creative-loom`. |
| 9–15 s | Data beat: the footage drops behind (blurred, darkened, or split-screen) while a 2D bar chart of `commits.csv` builds, one bar per beat, heights exactly proportional to the data. The tallest bar (34) is in the accent color with its value label. Day labels and a title, `COMMITS / DAY`, appear. |
| 15–18 s | Payoff: a fast run of 3–4 short cuts (the launch/celebration), ending on a held shot with a stat callout, `90 commits · 12 days`, that counts up. |
| 18–20 s | End card on `#0b0b0f`: `creative-loom` wordmark and a closing line of your choice. The music resolves or fades out cleanly by 20.0 s. |

Sound: the music should not clip (true peak ≤ −1 dBTP); aim for about −14 LUFS integrated. One or two sound effects (a whoosh on the transition, a hit on the stat) are welcome but optional.

Every cut and every bar lands on its beat, within one frame.

## Deliverables (in your run directory)

- `out/final.mp4`: H.264 yuv420p plus AAC, 1920×1080, 30 fps, 20 s.
- The source project or script that produced it (re-renderable), plus the downloaded media.
- `SOURCES.md`: every clip and the music, with URLs and licenses.
- `NOTES.md`, covering:
  - every beat, marked done, approximate, or impossible, with why;
  - your cut list (time in → time out, source clip and its in-point);
  - the number of renders, and render time per frame;
  - workarounds;
  - what was precise, and what fought you;
  - start and end times (run `date` at the start and at the end).

## Rules

- The editing (cuts, trims, reframing, transitions, timing), the motion graphics, the grade, and the audio placement must come from the assigned tool. Use `ffmpeg` only to download/transcode source media into a format the tool can read, to analyse audio, to mux audio if the tool cannot carry it, and to extract check frames. Don't pre-cut the edit in ffmpeg.
- Any helper language (Python, Bun, etc.) may be used for beat detection and data prep, not for rendering pixels.
- No paid generation (no AI video, image, music, or voice). Everything is sourced or built.
- Check your own work: extract frames at 1.0, 3.0, 5.5, 8.0, 11.0, 14.0, 16.5, and 19.0 s and look at them before calling it done. Listen-check the mix with numbers (loudness, true peak).
- Budget: about 60–90 minutes and 20 full renders at most. If a beat is impossible in your tool, say so and move on.
- Work only in your run directory. Don't read or list other directories under `runs/`.
TOOL.md: hyperframes
# Tool: HyperFrames (HTML compositions rendered to video)
CLI: `bunx hyperframes` (v0.8.140). Read the skills first: ~/.agents/skills/hyperframes/SKILL.md, then hyperframes-core, hyperframes-animation, hyperframes-keyframes (punch-ins, Ken Burns, transitions) and hyperframes-audio (mix). media-use covers footage cutting/reframing helpers; its HeyGen-backed `resolve` for music/SFX may not be signed in, so source music yourself if it fails. Footage and music go in the composition as `<video>`/`<audio>` elements (see hyperframes-core references).
TOOL.md: fframes
# Tool: fframes (Rust video framework: SVG scenes rendered on the GPU via Skia/Metal, ffmpeg encoding)
Read the skill first: cut-lab/.tools/fframes/skills/fframes-video/SKILL.md and its references (design.md, api.md, audio.md). The repo with examples is at cut-lab/.tools/fframes (see examples/ such as marketing, tiktok, motion-graphics). `cargo-fframes` is installed (`cargo fframes new <name> --format landscape --fps 30 --yes`); Rust is installed. Footage plays through `frame.get_synced_video_frame(...)`; music and SFX go in the audio map. Use the project CLI (`cargo run --release -- inspect | strip | frame | onion | audio analyze | render`) to check your work.
TOOL.md: effectcraft
# Tool: EffectCraft 0.3.1 (open-source After Effects clone in Rust)
CLI: cut-lab/.tools/effectcraft/effectcraft-cli (run with no args for usage; read cut-lab/.tools/effectcraft/README.md). The fastest path is `effectcraft-cli script build.jsx --save-as study.ecproj` with the After Effects-style object model (footage layers, precomps, masks, text animators, expressions, effects like Lumetri and Gaussian Blur), plus `render-frame` for checks and `render` for the movie. Known quirks: no function hoisting or String.substr in scripts; gradient colors must be set through `effectcraft-cli set ... colors '{"colors":[[0,"#hex"],...]}'`; keyframes snap to whole frames; footage passthrough is not bit-exact (slight softening), so don't fight it.
TOOL.md: tesseract
# Tool: Tesseract 0.3.1 by Mirage (native layer/composition engine, "the creative suite built for agents")
CLI: cut-lab/.tools/tesseract/bin/tesseract-0.3.1-darwin-arm64/bin/tsrct (run `--help`; telemetry is disabled; don't re-enable it).
Skills: read cut-lab/.tools/tesseract/skills/tesseract/skills/tesseract-motion/SKILL.md first and follow its references (installation, local-operation, native-authoring, motion-design, fx-authoring, motion, custom-shader). Pull exact fields from `tsrct project schema` and `tsrct project schema --document`. When the skill mentions an attribution variable, use TESSERACT_HOST=claude-code-lab.
Fonts must be imported from a TTF/OTF file; Jost is in the assets folder.

The take

Unlike round 2, every tool finished every beat. Editing and 2D motion graphics are within reach of all four, so what separates them is the friction an agent hits along the way. fframes rendered fastest by far; EffectCraft got to a finished cut first with the cleanest grade; Tesseract made the agent rediscover basic placement; HyperFrames lost most of its renders to audio that changed without telling anyone. A checklist brief also made the four cuts look alike, which is why round 4 threw the checklist out.

Frame counts, loudness, true peak and cut frames were measured on the final files. Players use 720p share copies. Footage and music: Mixkit, under the Mixkit free licenses.