Contenu
Créez une vidéo motion design avec HTML et Opus 5.5
Écrivez un beat sheet, demandez à Opus 5.5 de rédiger une scène HTML déterministe via l’API Felo, capturez les images avec Playwright et encodez un MP4 avec ffmpeg. Fonctionne dans WorkBuddy, ChatGPT avec exécution de code, Codex, Pi Agent ou Claude Code.
Copier le prompt
Remplacez les champs entre crochets, puis collez dans Claude Code, Codex ou toute IA avec accès au terminal. Elle installe le skill Felo, demande avant de dépenser des crédits et exécute le workflow.
Crée une vidéo de [durée] secondes, format [vertical / horizontal], sur [idée]. Style : [style]. Public : [public]. Audio : [aucun / une piste sous licence dans ./audio.mp3 / TTS]. Tu t’exécutes dans un dossier avec un terminal et [WorkBuddy / ChatGPT avec exécution de code / Codex / Pi Agent / Claude Code]. Si tu ne peux pas exécuter Node et un navigateur headless, arrête-toi et dis-le-moi au lieu de prétendre avoir rendu la vidéo. Procède dans cet ordre : 1. Écris un storyboard de 3 à 6 beats avec des secondes de début et de fin exactes. 2. Étape HTML : appelle Claude Opus 5.5 via l’API Felo. Utilise l’ID de modèle claude-opus-5-5 et ma clé FELO_API_KEY. Ne me demande pas d’abonnement Claude ni une autre clé Anthropic. 3. Demande à Opus un seul fichier HTML autonome : définir window.DURATION et exposer async window.seek(t). Aucun asset externe, CDN, Date.now(), requestAnimationFrame(), transition CSS ou minuteur. Seed toutes les valeurs aléatoires pour que le même t dessine toujours la même frame. 4. Prévisualise à t = 0, 25 %, 50 %, 75 % et sur la dernière frame. Vérifie les débordements, coupures, polices et zones sûres avant de tout rendre. 5. Rends chaque frame avec Playwright, encode en H.264 avec ffmpeg et mixe la piste audio si elle existe. 6. Montre la première frame, la dernière et le chemin du fichier final. Ne publie rien. Règles : - Avant de consommer des crédits, montre les appels à l’API Felo et l’estimation de tokens. - N’utilise que le texte que je fournis, ou signale clairement un texte de remplacement inventé. - N’utilise aucune image, musique, logo ou police sous copyright. Seulement des polices système et des formes générées. - Garde la vidéo finale sous 30 secondes, sauf si je demande explicitement un format long. - Écris tout dans ./video/ et résume les commandes exécutées.
La copie inclut aussi les étapes d'installation et les règles de sécurité.
Ce que vous obtenez
Exemple de sortie d'une exécution. Pas de génération en direct.
Rapport de rendu
Scène : video/scene.html (18 Ko) Durée : 12 s · 1080x1920 · 30 fps · 360 images Vérifications : window.DURATION = 12 · seek(t) présent · pas de Date.now / rAF / timers
Aperçu : preview-0ms.png · preview-3000ms.png · preview-6000ms.png · preview-9000ms.png Encodage : video/video.mp4 (H.264, 360 images) Audio : video/final.mp4 (AAC, 12,0 s)
Les appels exacts
Pour les développeurs : le même workflow en code, dans l'ordre d'exécution.
Afficher les appels API
Écrivez d’abord le beat sheet
Fixez la durée et 3 à 6 beats, chacun avec début, fin, texte à l’écran et changement visuel principal.
Générez la scène HTML avec Opus 5.5
Pointez l’Anthropic SDK vers l’URL de base Felo, utilisez le modèle
claude-opus-5-5et demandez uniquement le HTML avecwindow.DURATIONetasync 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`);Exemple de sortie
scene.html: 18432 bytes
Vérifiez le déterminisme et prévisualisez
Prenez des captures à t=0, 25 %, 50 %, 75 % et à la dernière image, en vérifiant débordement, polices et zones sûres.
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`);Exemple de sortie
duration 12s video/preview-0ms.png video/preview-3000ms.png video/preview-6000ms.png video/preview-9000ms.png
Rendez toutes les images et encodez
Appelez
seek(t)avect = frame / fps, capturez chaque image et encodez H.264 avec 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`);Exemple de sortie
360 frames -> video/video.mp4
Ajoutez l’audio et regardez en entier
Ajoutez la piste sous licence avec
-c:v copy, vérifiez durée et volume, puis regardez du début à la fin.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.mp4Exemple de sortie
12.000000
Itérez avec le même modèle
Décrivez uniquement l’image fautive et le changement voulu, transmettez le HTML actuel à Opus, relancez la prévisualisation avant le rendu complet.
Ce qui est inclus
- Storyboard et timeline écrits en amont
- Scène HTML déterministe générée par Opus 5.5
- Script de rendu Playwright et encodage ffmpeg
- MP4 final avec piste audio optionnelle
- Boucle de relecture et correction image par image
Ce qu'elle ne fait pas
- Opus 5.5 produit du code, pas des images ; le renderer du navigateur capture les images
- Pas d’abonnement Claude, mais l’usage du modèle Felo est facturé à l’usage
- Node, Playwright Chromium et ffmpeg restent nécessaires
- Pas d’éléments externes ni de CDN ; uniquement HTML/CSS/SVG/Canvas ou fichiers locaux
- Les longues vidéos demandent un découpage en scènes ; ce n’est pas une capture d’écran temps réel
- Narration et musique sont des étapes séparées ; le workflow ne fait que muxer votre audio
Questions
Opus 5.5 génère-t-il directement la vidéo ?
Non. Il produit texte et code en écrivant la scène HTML ; le navigateur et ffmpeg transforment la scène en images et MP4.
Faut-il un abonnement Claude ?
Non. Utilisez la clé Felo pour appeler `claude-opus-5-5` via l’API Felo, facturé à l’usage ; aucun abonnement Claude séparé n’est nécessaire.
Dans quels agents cela tourne-t-il ?
WorkBuddy, ChatGPT avec exécution de code, Codex, Pi Agent, Claude Code ou tout agent capable d’exécuter Node et un navigateur headless.
Pourquoi seek(t) dans la scène ?
La capture n’est pas en temps réel : l’image 400 peut être capturée bien après la 399, donc chaque image doit être une fonction pure de t.
Puis-je utiliser HyperFrames ou Remotion ?
Oui, pour des compositions longues ou structurées. Cette recette garde un seul HTML pour vérifier facilement l’appel au modèle et la boucle de rendu.
Combien coûte une vidéo de 12 secondes ?
Cela dépend du prompt, des tokens de sortie et des itérations. Le modèle Felo est facturé au token ; vérifiez les prix avant un long rendu.
Puis-je utiliser ma musique et ma narration ?
Oui, si vous avez les droits. Rendez d’abord la vidéo, puis muxez la piste sous licence ou votre TTS avec ffmpeg. Le workflow ne génère pas de narration.
Références
Tutoriels et projets sur lesquels repose ce workflow.
Workflows liés
Transformez une page de recherche en présentation
Extrayez la page, enregistrez-la comme contexte LiveDoc, laissez l’API PPT Task construire le deck et interrogez jusqu’au lien final.
Ouvrir le workflowContenuTransformez un brief produit en landing page
Étudiez l’audience, gardez le brief dans un LiveDoc, créez une tâche Landing Page à partir de ce contexte et interrogez jusqu’à ce que la page hébergée soit prête.
Ouvrir le workflowContenuRemplissez un mois de contenu avec les questions de votre audience
Cartographiez les thèmes avec Chat, trouvez les questions de l’audience sur X, prenez un angle réel dans une transcription vidéo et composez un calendrier de quatre semaines où chaque ligne nomme sa preuve.
Ouvrir le workflowAdaptez-la
La même recette, adaptée à votre façon de livrer.
Projet HyperFrames ou Remotion
Pour les longues compositions, utilisez ces frameworks ; l’appel au modèle reste le même, seule la commande de rendu change.
Version carrée pour les réseaux
Gardez le beat sheet, passez en 1080x1080 et ajustez typographie et zones sûres.
Trois variantes d’un brief
Générez trois scènes avec couleurs et rythmes différents, prévisualisez et ne rendez que la meilleure.
Aller plus loin
Les pages de référence derrière cette recette et la suite.