Felo API PlatformFelo API Platform

Conteúdo

Faça um vídeo de motion graphics com HTML e Opus 5.5

Escreva um beat sheet, peça ao Opus 5.5 para criar uma cena HTML determinística pela Felo API, capture os quadros com Playwright e codifique um MP4 com ffmpeg. Roda no WorkBuddy, ChatGPT com execução de código, Codex, Pi Agent ou Claude Code.

Tempo45 minutosNívelIntermediárioAtualizado2026-10-30
Para quemCriadoresMotion designersDesenvolvedores independentes

Copiar o prompt

Substitua os campos entre colchetes e cole no Claude Code, Codex ou qualquer IA com acesso ao terminal. Ela instala a skill da Felo, pergunta antes de gastar créditos e executa o fluxo.

Crie um vídeo de [duração] segundos, formato [vertical / horizontal], sobre [ideia].
Estilo: [estilo]. Público: [público]. Áudio: [nenhum / uma faixa licenciada em ./audio.mp3 / TTS].

Você roda em uma pasta com terminal e [WorkBuddy / ChatGPT com execução de código / Codex / Pi Agent / Claude Code]. Se não conseguir executar Node e um navegador headless, pare e me avise em vez de fingir que renderizou.

Siga esta ordem:
1. Escreva um storyboard de 3–6 beats com segundos exatos de início e fim.
2. Etapa HTML: chame Claude Opus 5.5 pela API da Felo. Use o ID de modelo claude-opus-5-5 e minha FELO_API_KEY. Não me peça assinatura do Claude nem outra chave Anthropic.
3. Peça ao Opus um único arquivo HTML autocontido: definir window.DURATION e expor async window.seek(t). Sem assets externos, CDN, Date.now(), requestAnimationFrame(), transições CSS ou timers. Semeie todos os valores aleatórios para que o mesmo t desenhe sempre o mesmo frame.
4. Pré-visualize em t = 0, 25%, 50%, 75% e no último frame. Verifique overflow, cortes, fontes e áreas seguras antes de renderizar tudo.
5. Renderize cada frame com Playwright, codifique em H.264 com ffmpeg e faça o mux da faixa de áudio, se houver.
6. Mostre o primeiro frame, o último e o caminho final. Não publique.

Regras:
- Antes de gastar créditos, mostre as chamadas à API da Felo e a estimativa de tokens.
- Use apenas o texto que eu fornecer, ou marque claramente texto de preenchimento inventado.
- Não use material, música, logotipo ou fonte protegidos por direitos autorais. Só fontes do sistema e formas geradas.
- Mantenha o vídeo final abaixo de 30 segundos, a menos que eu peça um formato longo.
- Grave tudo em ./video/ e resuma os comandos executados.

A cópia também inclui os passos de instalação e as regras de segurança.

O que você recebe

Saída de exemplo de uma execução. Não é geração ao vivo.

Exemplo de relatório de render (trecho)

Relatório de render

Cena: video/scene.html (18 KB) Duração: 12 s · 1080x1920 · 30 fps · 360 quadros Checagens: window.DURATION = 12 · seek(t) presente · sem Date.now / rAF / timers

Prévia: preview-0ms.png · preview-3000ms.png · preview-6000ms.png · preview-9000ms.png Codificação: video/video.mp4 (H.264, 360 quadros) Áudio: video/final.mp4 (AAC, 12,0 s)

As chamadas exatas

Para desenvolvedores: o mesmo fluxo em código, na ordem de execução.

Mostrar as chamadas reais da API
  1. Escreva o beat sheet primeiro

    Fixe a duração e de 3 a 6 beats, cada um com início, fim, texto na tela e principal mudança visual.

  2. Gere a cena HTML com o Opus 5.5

    Aponte o Anthropic SDK para a base URL da Felo, use o modelo claude-opus-5-5 e peça apenas o HTML, com 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`);

    Saída de exemplo

    scene.html: 18432 bytes
  3. Verifique o determinismo e pré-visualize quadros

    Tire screenshots em t=0, 25%, 50%, 75% e no último quadro, conferindo estouro de texto, fontes e áreas seguras.

    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`);

    Saída de exemplo

    duration 12s
    video/preview-0ms.png
    video/preview-3000ms.png
    video/preview-6000ms.png
    video/preview-9000ms.png
  4. Renderize todos os quadros e codifique

    Chame seek(t) com t = frame / fps, capture screenshots e codifique H.264 com 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`);

    Saída de exemplo

    360 frames -> video/video.mp4
  5. Adicione áudio e assista inteiro

    Inclua a trilha licenciada com -c:v copy, confira duração e volume e assista do início ao fim.

    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

    Saída de exemplo

    12.000000
  6. Itere com o mesmo modelo

    Descreva só o quadro com problema e a mudança desejada, passe o HTML atual ao Opus e rode a prévia antes do render completo.

O que está incluído

  • Storyboard e linha do tempo escritos primeiro
  • Uma cena HTML determinística criada pelo Opus 5.5
  • Script de renderização do Playwright e codificação no ffmpeg
  • MP4 final com trilha de áudio opcional
  • Ciclo de revisão e correção quadro a quadro

O que não faz

  • O Opus 5.5 gera código, não quadros de vídeo; o renderizador do navegador captura os quadros
  • Não precisa de assinatura do Claude, mas o uso do modelo Felo é cobrado por uso
  • O ambiente ainda precisa de Node, Playwright Chromium e ffmpeg
  • Sem materiais externos nem CDN: só HTML/CSS/SVG/Canvas ou arquivos locais
  • Vídeos longos exigem divisão em cenas; não é gravação de tela em tempo real
  • Narração e música são etapas separadas; o fluxo só adiciona o áudio fornecido

Perguntas

O Opus 5.5 gera vídeo diretamente?

Não. Ele gera texto e código, escrevendo a cena HTML; o navegador e o ffmpeg transformam a cena em quadros e MP4.

Preciso de assinatura do Claude?

Não. Use a chave da Felo para chamar `claude-opus-5-5` pela Felo API com cobrança por uso; não é preciso comprar assinatura do Claude.

Em quais agents isso roda?

WorkBuddy, ChatGPT com execução de código, Codex, Pi Agent, Claude Code ou qualquer agent que rode Node e um navegador headless.

Por que a cena precisa de seek(t)?

A captura não é em tempo real: o quadro 400 pode ser capturado muito depois do 399, então cada quadro precisa ser uma função pura de t.

Posso usar HyperFrames ou Remotion?

Sim, para composições longas ou projetos estruturados. Esta receita mantém um único HTML para facilitar a inspeção da chamada e do loop de renderização.

Quanto custa um vídeo de 12 segundos?

Depende do prompt, dos tokens de saída e das iterações. O modelo Felo cobra por token; confira os preços atuais antes de um render longo.

Posso usar minha música e narração?

Sim, se tiver os direitos. Renderize o vídeo primeiro e adicione a trilha licenciada ou seu TTS com ffmpeg. O fluxo não gera narração.

Referências

Tutoriais e projetos nos quais este fluxo se baseia.

Fluxos relacionados

Faça do seu jeito

A mesma receita, adaptada ao seu processo real.

Projeto HyperFrames ou Remotion

Para composições longas, use esses frameworks; a chamada do modelo é a mesma e só muda o comando de render.

Versão quadrada para redes

Mantenha o beat sheet, mude para 1080x1080 e ajuste tipografia e áreas seguras.

Três variações de um briefing

Gere três cenas com cores e ritmos diferentes, pré-visualize e renderize apenas a melhor.

As páginas de referência por trás desta receita e para onde ir depois.