The result: one week in 74 seconds.
The request was a single sentence: “summarise last week as a script, then make a motion-graphics animation with screenshots of the sources and Aaron’s voice from ElevenLabs”. The material: the WhatsApp export of a developer group, 5 MB of text. The agent returned two things: a Markdown script and this video (in Spanish).
Every scene has a diagram that draws itself to the rhythm of the voice, a number that appears exactly when it is spoken, and a real screenshot of the source: the GitHub repository, the model ranking, the migrated website. No stock footage, no templates.
The architecture: one orchestrator, six tools.
The model does not “generate a video”. Opus acts as the director: it reads, decides, writes code and calls tools. Each tool does one thing well:
- Reading the chat: a shell in a sandbox (
grep,sed) to cut just the last week out of a 55,000-line file. - Script: the model itself picks 8 stories with concrete numbers and writes the voiceover.
- Voice: ElevenLabs generates four takes with the “Aaron Abad – Storyteller en Castellano” voice.
- Timestamps: Scribe, the ElevenLabs transcriber, returns the start and end of every word.
- Screenshots: the built-in browser of the Claude app opens each source on your computer.
- Render: a canvas animation engine, headless Chromium and ffmpeg, with automatic loudness and sync checks.
Everything hangs off one file, score.js, which holds the time of every cut, every number and every caption. Sound and picture both read it, so they cannot drift apart.
From chat to script.
A 5 MB export does not fit in one read. The agent first counts messages per day to find the window, then extracts only those lines:
for d in 12 13 14 15 16 17 18 19; do
echo "$d/10: $(grep -c "^\[$d/10/2026" chat.txt)"
done
grep -n "^\[12/10/2026" chat.txt | head -1 # → line 54021
sed -n '54021,$p' chat.txt > week.txt # 1,304 linesWith the week in context, editorial judgement makes the difference: stories with a number you can animate (24 hours, 80 %, 150 customers), credited by name, and nothing political or personal. The script is a table with four columns: scene, visual, voiceover and note. It is delivered before spending voice credits, so the direction can still change.
Someone in the chat said Meta had “the second-best model”. The agent opened the source and the page said #4 of 696. The video says what the page says.
The voice: four takes, pick the cleanest.
The agent finds the voice by name with creative_list_voices (never an id from memory) and generates the full text with eleven_v4. ElevenLabs returns four variations: 71, 76, 76 and 78 seconds. We picked the shortest, because in a recap pace matters more than dramatic pauses.
A practical detail: separating scenes with a paragraph break in the text gives natural pauses of half a second or more. Those pauses are exactly where the scene cuts will land.
Word timestamps: the voice is in charge.
Instead of guessing when each thing is said, the agent transcribes the chosen take with Scribe and gets a list like this:
{ "text": "Meta", "start": 18.80, "end": 18.98 },
{ "text": "arriba", "start": 21.70, "end": 22.00 },
{ "text": "80", "start": 39.42, "end": 39.60 },
{ "text": "%", "start": 39.92, "end": 39.96 }With that, the “#4” stamp lands at 21.70 s (when the voice says “arriba”, “on top”) and the 80 % ring starts filling at 39.42 s. Each scene cut is placed in the silence just before the first word of the next topic.
Real screenshots, routed through your computer.
The sandbox the agent works in has no open internet access: neither to news sites nor to the storage where ElevenLabs leaves the MP3. The fix was to use the user’s computer as a bridge, through the built-in browser of the Claude app.
Screenshots: the agent opens each source, sets the viewport to 1440×900, dismisses modal notices and takes a screenshot. Each screenshot lands in the sandbox as a JPG.

Audio: for the 1.1 MB MP3, the agent downloads it inside the page, base64-encodes it and reads it back in chunks of 200,000 characters, eight calls in parallel. Then it rebuilds the file in the sandbox:
const buf = new Uint8Array(await (await fetch(location.href)).arrayBuffer());
let s = ''; for (let i = 0; i < buf.length; i += 32768)
s += String.fromCharCode.apply(null, buf.subarray(i, i + 32768));
window.__b64 = btoa(s); // 1,546,492 characters
// then, 8 times: 'C3<' + window.__b64.slice(600000, 800000) + '>'One score for sound and picture.
The engine comes from the animation-studio skill: every frame is drawn in code on a canvas and the soundtrack is synthesized in JavaScript. Its golden rule is that every event lives in score.js:
const VOFF = 0.5; // the voice starts at 0.5 s
const S = { // cuts inside the voice's pauses
intro: [0, 6.55], claudio: [6.55, 19.1], meta: [19.1, 24.85],
rea: [24.85, 35.05], german: [35.05, 46.65], debate: [46.65, 56.45],
homedock: [56.45, 64.95], outro: [64.95, 74.5],
};
const w = (x) => x + VOFF; // a word's time from Scribe
const ev = { rank: w(21.7), wallet80: w(39.42), rip: w(57.72) };song.js reads those times to put a hit on every cut and a pop on every number; film.js reads them to bring every element in. Move a number in the score and the sound and picture move together.
Drawing scenes as functions of time.
Each scene is a pure function draw(ctx, t): given an instant, it draws exactly that frame. That way several Chromium processes can render in parallel and get identical images. Five reusable pieces build every scene:
- browser(): a browser window with the real URL and the screenshot inside, slowly zooming toward the part that matters.
- box() and arrow(): nodes and animated dashed arrows for the diagrams.
- Data.counter and UI.ring: counters that climb to the number and percentage rings.
- stampAt(): bouncing stamps for verdicts (“#4”, “RIP CLOUD”, “VALIDADOR NEGACIONISTA”).
- Subs.draw: phrase-level captions timed by Scribe.




Mix and measure, don’t listen.
The agent cannot hear, so it measures. Under the voice runs a synthesized lo-fi bed that ducks automatically whenever someone speaks. The first measurement showed the bass 4 dB above the voice; after adjusting gains the voice sat about 7 dB above everything else:
intro claudio meta rea
stem-voice -23.6 -22.8 -22.0 -22.2
stem-bass -31.6 -29.4 -28.9 -29.1
stem-keys -30.0 -31.8 -32.0 -30.6
integrated loudness: -14.0 LUFS−14 LUFS is the level YouTube and Spotify normalise to; the limiter keeps the true peak under −1.5 dBTP so AAC encoding does not clip it.
Render, review and verify.
Before the full render, the agent renders one frame per scene at half resolution, tiles them into a sheet and reviews it like a director: overlapping text, a character hidden behind a stamp, labels on top of the title. The first review found and fixed those overlaps.

Rendering 2,235 frames took about five minutes. Then verify measures in the final MP4 whether every cut lands on the right frame and whether its sound hit is within 20 ms. On four cuts, a syllable of the voice started 0.1 s from the hit and masked it; the tool flagged them as unclear. The honest fix was to mark those cuts as picture-only, not to move times by hand.
marker score sound picture
claudio 6.550s 6.555s +5ms ✓ 6.600s +1f ✓
meta 19.100s 19.105s +5ms ✓ 19.133s +1f ✓
outro 64.950s 64.955s +5ms ✓ 65.000s +1f ✓
✓ in syncChromium running as root needs --no-sandbox: solved with a wrapper script in CHROME_PATH, without touching the engine. And the built-in browser does not save downloads to your folder, which is why the audio travels as base64.
Turn the process into a skill.
The most valuable output of the session is not the video but the procedure. We saved it as a skill, chat-recap-motion-video: a SKILL.md with the steps, the defaults (voice, length, style), the networking tricks and the checks. Any Claude instance on the account loads it when someone asks for “last week as a video”, and its last section asks for lessons to be added after every run.
- Input: a chat export or notes, and the period.
- Early delivery: the script, before any credits are spent.
- Final delivery: MP4, script, credits spent, sources captured and what was left out.
Rough cost of this piece: about 5,300 ElevenLabs credits for the four voice takes and about 390 for the transcription. Rendering is local and costs no credits.
The prompt to do it yourself.
With Claude Opus, the desktop app linked to your computer, ElevenLabs as a connector and the animation-studio skill installed:
Attached is our group chat export. Summarise the last week as a script
(scene · visual · voiceover) and send it to me first.
Then make a ~75 s 16:9 motion-graphics video:
- voiceover with ElevenLabs (pick a voice that fits the language)
- word timestamps to sync cuts, numbers and captions
- one real screenshot of each story's source (use the browser)
- one animated diagram per scene, plus captions
Leave out politics and personal matters. Verify loudness (−14 LUFS)
and sync, and tell me how many credits you spent.The natural next step is a vertical 9:16 cut for Reels and Shorts. Cropping won’t do it: every scene has to be recomposed for a phone screen. If you build it, tell us how it went.