Render a 9:16 motion graphic video with Claude Code and HyperFrames, no AI video model
How a coding agent renders a 1080×1920 vertical motion video from a recipe: React composition, HyperFrames (Apache 2.0), headless Chrome, FFmpeg.
Duchamp
Short answer
You do not need Sora, Veo or any video model for a text-led announcement video. Give Claude Code or Codex a recipe: the agent writes a small React composition, HyperFrames renders every frame in headless Chrome, FFmpeg encodes a 1080×1920 MP4, and code checks the result before you see it. Duchamp publishes three such recipes.
What is HyperFrames?
HyperFrames is an open-source framework whose tagline is "Write HTML. Render video. Built for agents." It is licensed under Apache 2.0. A composition is a plain HTML file. Timing and tracks are declared with data-* attributes such as data-start, data-duration and data-track-index, clips carry class="clip", and animation comes from a seekable runtime through adapters for GSAP, CSS, Lottie, Three.js, Anime.js or the Web Animations API. The renderer seeks to each frame in headless Chrome and, in the project's own words, "encodes the result with FFmpeg". The CLI covers init, preview, render, add and skills.
Duchamp's recipes use it one layer up. The agent writes a React composition in TypeScript; a small helper bundles it with esbuild into a single index.html, and the HyperFrames CLI renders that file. HyperFrames only ever sees HTML, which is why the browser is the only runtime the video needs.
Duchamp moved its recipes to HyperFrames on October 6, 2026. The deciding reason was the license. The recipe is run on your machine, so whatever the renderer requires is required of you. Apache 2.0 puts no obligation on the person running it. In our own test the same composition also rendered noticeably faster and with far less memory than the previous renderer.
| Same 5.4 s composition, 30 fps, one machine | Previous renderer | HyperFrames |
|---|---|---|
| Render time, warm | 41.4 s | 10.1 s |
| Peak memory (browser, node, ffmpeg) | about 5.5 GB | about 1.8 to 2.2 GB |
Which recipes does Duchamp publish?
Three at the time of writing, all 9:16, 1080×1920, silent MP4, each with an example rendered from the recipe for a fictional brand.
| Recipe | What it does | Length | Scenes | Frame rate | Best for |
|---|---|---|---|---|---|
| Change notice | Shows each change as a before-to-after line in a ledger: a pen strikes the old value, an arrow is drawn, the new value rises, a highlighter band settles under it | about 12 s | 3 to 5 cuts | 30 fps | New opening hours, a closed day, a price change |
| Opening countdown | A full-screen tear-off calendar; each cut is a day, the page curls and tears upward to reveal the next, from D-3 to opening day | about 11 s | 3 to 5 cuts | 30 fps | Counting down to a shop, space or service opening |
| Event announcement | What, when and where, how to join, and a closing mark; each scene enters fast, holds completely still to be read, then accelerates out as the next scene pushes up at the same speed | about 14 s | 3 to 4 scenes | 60 fps | Markets, book talks, meetups with a fixed date and place |
Names are Duchamp's. The MCP ids are video.change-notice-video, video.open-countdown-video and video.event-info-video.
How does the flow work?
- Copy the recipe. On the web it is the copy button on the recipe page; over MCP it is
search_image_templateswithuse: video, thenget_templatewith the id. - Paste it into Claude Code or Codex and fill the blanks at the top: brand name, three HEX colors (paper, ink, accent), the topic and the text for each scene. If a blank is left as
[ ], the agent is told to stop and ask rather than invent. - The agent saves the code files exactly as given and writes one file,
props.json, from your answers. Facts you did not give staynull. The recipe forbids filling a date, price or headcount from a guess. npm installpulls HyperFrames, esbuild, React and a static FFmpeg into that folder only. On first run HyperFrames downloads headless Chrome, about 190 MB, into the project's.render/home.node render.mjs mp4renders stills for every scene, a contact sheet, a beat map and the MP4, then runs the checks below. The event recipe reports about 30 seconds to a minute.- The agent opens the stills, compares them against a checklist and reports paths, the motion profile and one line: this video is silent, add music in your editing app.
What timing rules make it motion design rather than a slideshow?
The event recipe was built by taking a real event teaser apart frame by frame and measuring. The rule it extracted is hold plus fast move: text enters quickly, stops completely so it can be read, then leaves with acceleration while the next scene pushes in at the same speed. No fades, no camera drift, no shake.
| Element | Rule in the code |
|---|---|
| Entrance | Exponential deceleration, each 30 fps frame closes 85% of the remaining distance (τ 0.205 s), starting 648 to 675 px below, no overshoot |
| Opacity | A stair per line, 0.2 to 0.23 s apart; the group rises as one, only opacity is staggered |
| Hold | Fully still for 1.3 to 2 s per scene, computed as 0.8 s plus 0.03 s per character |
| Exit | Exponential acceleration, ×1.23 per frame (τ 0.161 s); labels leave 0.07 s earlier and 1.3× faster |
| Transition | One push: the next scene starts 0.6 s later in the same direction at the exit speed, about five frames of overlap |
| Closing | A color plate fills in 0.3 s, settles into a band, splits into three lines, bends into an abstract mark over 0.75 s |
| Motion profile | Reference teaser measured 53% hold, 15% slow drift, 32% large movement; the code lands at 56 to 61, 16 to 24, 15 to 26 |
The event recipe renders at 60 fps with four sub-frames per frame, spaced 1/240 s apart and averaged. Moving text blurs the way a camera would; the moment it stops it is pin sharp. The two 30 fps recipes bake their own motion into the drawing instead: a torn page curling, a pen stroke being laid down.
What does the code check before handing you the file?
Each scene is checked at its still frames: the on-screen text joins back into exactly the input, nothing sits in the unsafe zones (top 12%, bottom 35%, 64 px at the sides), contrast clears, large type stays above its floor, letters do not collide with each other or with graphics. The MP4 is then measured: hold between 40% and 65% of the runtime, slow drift under 30%, each scene still for 1.0 to 2.2 s, zero popping frames, correct size and frame rate, no audio track.
A failed check stops with a named reason. Input problems such as text too long or an accent too close to the background go back to you as a question. Code problems are reported verbatim; the agent is told not to patch the renderer.
When is this the wrong tool?
When the video needs footage, people or generated scenes. When the music has to be baked in. When you want a minute of content rather than ten to fifteen seconds of announcement. The recipes are for text-led vertical announcements where every word on screen is a fact you supplied, and they are deliberately silent about everything else.
FAQ
- Do I need to know React to use a video recipe?
- No. The recipe contains the composition code in full and tells the agent to save it byte for byte. The only file the agent writes is props.json with your brand name, three colors and the text for each scene. Sizes, line breaks and timing are computed by the code.
- Does rendering work inside the Codex sandbox?
- Installing needs the network and rendering needs to launch headless Chrome. On macOS the sandbox blocks Chrome, and the recipe tells the agent to ask you for an elevated run instead of working around it. Claude Code without a sandbox renders directly.
- Why is the MP4 silent?
- The recipes never add music, sound effects or voice, because a bundled track would carry licensing you did not choose. Add music in Instagram or a video editor afterwards. The agent is told to say this in its report.
- Can I change the timing or make it faster?
- Not by hand. Hold lengths, easing and transition speed are fixed in the code and checked after the render, because that is where the reference quality lives. Variation comes from your text, colors, the optional texture plate and the closing mark, not from retiming.
Related
- Landing page and hero section references your coding agent can use over MCPWhy a vibe-coded landing page needs a reference, and how Duchamp UI, 21st.dev, Mobbin, shadcn/ui and Magic UI compare for Claude Code and Codex users.
- A vector logo kit from a coding agent: SVG, PNG, favicon and OG image without an image modelHow a recipe turns real font outlines into a logo kit by code: mark, wordmark, lockups, dark and mono versions, favicons, app icons and OG image.