Felo API PlatformFelo API Platform

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.

Tempo45 minutiLivelloIntermedioAggiornato2026-10-30
Per chiCreatorMotion designerSviluppatori indipendenti

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.

Esempio di report render (estratto)

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
  1. Scrivi prima il beat sheet

    Fissa durata e 3–6 beat, ciascuno con inizio, fine, testo a schermo e principale cambio visivo.

  2. Genera la scena HTML con Opus 5.5

    Punta l’Anthropic SDK alla base URL Felo, usa claude-opus-5-5 e chiedi solo HTML con window.DURATION e 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`);

    Output di esempio

    scene.html: 18432 bytes
  3. 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
  4. Renderizza tutti i frame e codifica

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

    Output di esempio

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

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

Le pagine di riferimento dietro questa ricetta e i prossimi passi.