Felo API PlatformFelo API Platform

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.

Temps45 minutesNiveauIntermédiaireMis à jour2026-10-30
Pour quiCréateursMotion designersDéveloppeurs indépendants

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.

Exemple de rapport de rendu (extrait)

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
  1. É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.

  2. 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-5 et demandez uniquement le HTML avec window.DURATION et async 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
  3. 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
  4. Rendez toutes les images et encodez

    Appelez seek(t) avec t = 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
  5. 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.mp4

    Exemple de sortie

    12.000000
  6. 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

Adaptez-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.

Les pages de référence derrière cette recette et la suite.