Contenuti
Crea un video motion graphics con HTML e Opus 5.5
Scrivi un beat sheet, chiedi a Opus 5.5 una scena HTML deterministica via Felo API, cattura i frame con Playwright e codifica un MP4 con ffmpeg. Funziona in WorkBuddy, ChatGPT con esecuzione codice, Codex, Pi Agent o Claude Code.
Copia il prompt
Sostituisci i campi tra parentesi quadre e incolla in Claude Code, Codex o qualsiasi IA con accesso al terminale. Installa lo skill Felo, chiede prima di spendere crediti ed esegue il workflow.
Crea un video di [durata] secondi, formato [verticale / orizzontale], su [idea]. Stile: [stile]. Pubblico: [pubblico]. Audio: [nessuno / una traccia con licenza in ./audio.mp3 / TTS]. Lavori in una cartella con terminale e [WorkBuddy / ChatGPT con esecuzione di codice / Codex / Pi Agent / Claude Code]. Se non puoi eseguire Node e un browser headless, fermati e dimmelo invece di fingere di aver renderizzato. Procedi in questo ordine: 1. Scrivi uno storyboard di 3–6 beat con secondi esatti di inizio e fine. 2. Fase HTML: chiama Claude Opus 5.5 tramite l’API Felo. Usa l’ID modello claude-opus-5-5 e la mia FELO_API_KEY. Non chiedermi un abbonamento Claude né un’altra chiave Anthropic. 3. Chiedi a Opus un unico file HTML autonomo: impostare window.DURATION ed esporre async window.seek(t). Nessun asset esterno, CDN, Date.now(), requestAnimationFrame(), transizione CSS o timer. Imposta il seed di ogni valore casuale così lo stesso t disegna sempre lo stesso frame. 4. Anteprima a t = 0, 25%, 50%, 75% e sull’ultimo frame. Controlla overflow, tagli, font e aree sicure prima di renderizzare tutto. 5. Renderizza ogni frame con Playwright, codifica in H.264 con ffmpeg e muxa la traccia audio se presente. 6. Mostra il primo frame, l’ultimo e il percorso finale. Non pubblicare. Regole: - Prima di consumare crediti, mostra le chiamate all’API Felo e la stima dei token. - Usa solo il testo che ti do, oppure segna chiaramente il testo segnaposto inventato. - Non usare materiali, musica, loghi o font protetti da copyright. Solo font di sistema e forme generate. - Tieni il video finale sotto i 30 secondi, a meno che io chieda esplicitamente un formato lungo. - Scrivi tutto in ./video/ e riassumi i comandi eseguiti.
La copia include anche i passaggi di installazione e le regole di sicurezza.
Cosa ottieni
Output di esempio di un'esecuzione. Non è generazione dal vivo.
Report di render
Scena: video/scene.html (18 KB) Durata: 12 s · 1080x1920 · 30 fps · 360 frame Controlli: window.DURATION = 12 · seek(t) presente · nessun Date.now / rAF / timer
Anteprima: preview-0ms.png · preview-3000ms.png · preview-6000ms.png · preview-9000ms.png Codifica: video/video.mp4 (H.264, 360 frame) Audio: video/final.mp4 (AAC, 12,0 s)
Le chiamate esatte
Per gli sviluppatori: lo stesso workflow come codice, nell'ordine di esecuzione.
Mostra le chiamate API reali
Scrivi prima il beat sheet
Fissa durata e 3–6 beat, ciascuno con inizio, fine, testo a schermo e principale cambio visivo.
Genera la scena HTML con Opus 5.5
Punta l’Anthropic SDK alla base URL Felo, usa
claude-opus-5-5e chiedi solo HTML conwindow.DURATIONeasync seek(t).generate-scene.ts import { mkdir, writeFile } from "node:fs/promises"; import Anthropic from "@anthropic-ai/sdk"; const SYSTEM = `You write a single, self-contained HTML video scene. Requirements: - 1080x1920 (or 1920x1080), no external assets, system fonts only. - set window.DURATION = <seconds>. - expose async window.seek(t) that draws the frame for time t. - no Date.now(), no requestAnimationFrame(), no CSS transitions, no timers. - seed every random value; the same t must always produce the same frame. - return only the HTML file, no markdown fences.`; const brief = `12-second vertical motion graphic about [idea]. Beats: [0-3s hook], [3-7s point], [7-10s proof], [10-12s CTA]. Palette: [colors]. Type: system sans. Keep text inside a 64px safe area.`; const anthropic = new Anthropic({ apiKey: process.env.FELO_API_KEY, baseURL: "https://openapi.felo.ai/api", }); const message = await anthropic.messages.create({ model: "claude-opus-5-5", max_tokens: 32000, system: SYSTEM, messages: [{ role: "user", content: brief }], }); const raw = message.content .filter((block) => block.type === "text") .map((block) => block.text) .join(""); const html = raw.replace(/^```(?:html)?\s*/i, "").replace(/```\s*$/, "").trim(); await mkdir("video", { recursive: true }); await writeFile("video/scene.html", html); console.log(`scene.html: ${html.length} bytes`);Output di esempio
scene.html: 18432 bytes
Verifica determinismo e anteprima
Scatta screenshot a t=0, 25%, 50%, 75% e ultimo frame, controllando overflow, font e aree sicure.
preview.ts import { chromium } from "playwright"; import { pathToFileURL } from "node:url"; const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1080, height: 1920 }, deviceScaleFactor: 1, }); await page.goto(pathToFileURL("video/scene.html").href); await page.waitForFunction(() => typeof (window as any).seek === "function"); const duration = await page.evaluate(() => (window as any).DURATION as number); for (const t of [0, duration * 0.25, duration * 0.5, duration * 0.75]) { await page.evaluate(async (time) => { await (window as any).seek(time); }, t); await page.screenshot({ path: `video/preview-${Math.round(t * 1000)}ms.png` }); } await browser.close(); console.log(`duration ${duration}s`);Output di esempio
duration 12s video/preview-0ms.png video/preview-3000ms.png video/preview-6000ms.png video/preview-9000ms.png
Renderizza tutti i frame e codifica
Chiama
seek(t)cont = frame / fps, cattura e codifica H.264 con ffmpeg.render.ts import { spawn } from "node:child_process"; import { mkdir, rm } from "node:fs/promises"; import { pathToFileURL } from "node:url"; import { chromium } from "playwright"; const FPS = 30; const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1080, height: 1920 }, deviceScaleFactor: 1, }); await page.goto(pathToFileURL("video/scene.html").href); await page.waitForFunction(() => typeof (window as any).seek === "function"); const duration = await page.evaluate(() => (window as any).DURATION as number); const frames = Math.ceil(duration * FPS); await rm("video/frames", { recursive: true, force: true }); await mkdir("video/frames", { recursive: true }); for (let frame = 0; frame < frames; frame++) { await page.evaluate(async (time) => { await (window as any).seek(time); }, frame / FPS); await page.screenshot({ path: `video/frames/${String(frame).padStart(5, "0")}.png`, }); } await browser.close(); const ffmpeg = spawn("ffmpeg", [ "-y", "-framerate", String(FPS), "-i", "video/frames/%05d.png", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-movflags", "+faststart", "video/video.mp4", ], { stdio: "inherit" }); await new Promise<void>((resolve, reject) => { ffmpeg.on("exit", (code) => { if (code === 0) resolve(); else reject(new Error(`ffmpeg exited with ${code}`)); }); }); console.log(`${frames} frames -> video/video.mp4`);Output di esempio
360 frames -> video/video.mp4
Muxa audio e guarda tutto
Aggiungi la traccia con licenza con
-c:v copy, controlla durata e volume e guarda dall’inizio alla fine.mux.sh ffmpeg -i video/video.mp4 -i video/audio.wav \ -c:v copy -c:a aac -b:a 192k -shortest \ video/final.mp4 ffprobe -v error -show_entries format=duration \ -of default=nw=1:nk=1 video/final.mp4Output di esempio
12.000000
Itera con lo stesso modello
Descrivi solo il frame sbagliato e la modifica desiderata, passa l’HTML attuale a Opus e rilancia l’anteprima prima del render completo.
Cosa include
- Storyboard e timeline scritti prima
- Scena HTML deterministica di Opus 5.5
- Script di render Playwright e codifica ffmpeg
- MP4 finale con traccia audio opzionale
- Ciclo di revisione e correzione frame per frame
Cosa non fa
- Opus 5.5 produce codice, non frame; il renderer del browser cattura i frame
- Nessun abbonamento Claude, ma l’uso del modello Felo è a consumo
- Servono ancora Node, Playwright Chromium e ffmpeg
- Niente asset esterni o CDN; solo HTML/CSS/SVG/Canvas o file locali
- I video lunghi richiedono divisione in scene; non è registrazione schermo in tempo reale
- Narrazione e musica sono passi separati; il workflow muxa solo audio fornito
Domande
Opus 5.5 genera video direttamente?
No. Genera testo e codice scrivendo la scena HTML; browser e ffmpeg trasformano la scena in frame e MP4.
Serve un abbonamento Claude?
No. Usa la chiave Felo per chiamare `claude-opus-5-5` via Felo API, a consumo; non serve un abbonamento Claude separato.
In quali agent funziona?
WorkBuddy, ChatGPT con esecuzione codice, Codex, Pi Agent, Claude Code o qualsiasi agent che esegua Node e un browser headless.
Perché seek(t)?
La cattura non è in tempo reale: il frame 400 può essere catturato molto dopo il 399, quindi ogni frame deve essere funzione pura di t.
Posso usare HyperFrames o Remotion?
Sì, per composizioni lunghe o progetti strutturati. Questa ricetta mantiene un solo HTML per controllare chiamata e ciclo di render.
Quanto costa un video di 12 secondi?
Dipende da prompt, token di output e iterazioni. Il modello Felo fattura per token; controlla i prezzi prima di un render lungo.
Posso usare la mia musica e narrazione?
Sì, se hai i diritti. Renderizza prima e muxa la traccia con licenza o il tuo TTS con ffmpeg. Il workflow non genera narrazione.
Riferimenti
Tutorial e progetti su cui si basa questo workflow.
Workflow correlati
Trasforma una pagina di ricerca in una presentazione
Estrai la pagina, salvala come contesto LiveDoc, lascia che la PPT Task API costruisca il deck e interroga finché il link è pronto.
Apri il workflowContenutiTrasforma un brief di prodotto in una landing page
Studia il pubblico, salva il brief in un LiveDoc, crea un’attività Landing Page da quel contesto e interroga finché la pagina ospitata è pronta.
Apri il workflowContenutiRiempi un mese di contenuti con le domande del tuo pubblico
Mappa i temi con Chat, trova le domande del pubblico su X, prendi un angolo reale da una trascrizione video e componi un calendario di quattro settimane in cui ogni riga nomina la sua prova.
Apri il workflowAdattala a te
La stessa ricetta, adattata a come lavori davvero.
Progetto HyperFrames o Remotion
Per composizioni lunghe usa questi framework; la chiamata al modello è uguale e cambia solo il comando di render.
Versione quadrata per social
Mantieni il beat sheet, passa a 1080x1080 e regola tipografia e aree sicure.
Tre varianti da un brief
Genera tre scene con colori e ritmi diversi, guarda le anteprime e renderizza solo la migliore.
Continua
Le pagine di riferimento dietro questa ricetta e i prossimi passi.