Habilidade de Geração de Vídeo Programática
Um fluxo de trabalho determinístico, sem boilerplate, para agentes de IA codificadores projetarem, revisarem visualmente, pontuarem e renderizarem vídeos MP4 animados em 1080p e 60fps diretamente de um único arquivo HTML5 Canvas/SVG, um script de áudio procedural em Python e um pipe headless Playwright → FFmpeg.
Caminhos. ${CLAUDE_SKILL_DIR} é o diretório que contém este SKILL.md. No Claude Code ele se expande automaticamente; no Cursor, Codex, OpenCode ou outros agentes, substitua ${CLAUDE_SKILL_DIR} pelo caminho resolvido para skills/programmatic-video/.
Por que Step de Quadros Determinístico?
Nunca use gravação de tela em tempo real (MediaRecorder, captura de relógio de parede requestAnimationFrame ou transições CSS em execução em tempo real) para produzir vídeos com um agente de IA:
- A captura por relógio de parede perde quadros sempre que a carga da CPU aumenta, causando desvio de áudio/vídeo e gagueira.
- Animações CSS rodam no tempo de parede, tornando impossível buscar para
t = 14,20spara uma revisão visual instantânea. - Renderização cega desperdiça minutos: renderizar 5.000 quadros antes de verificar se um título transborda seu cartão garante trabalho desperdiçado.
Em vez disso, cada vídeo construído com esta habilidade obedece a três regras:
- Regra 1 — Função Pura do Índice do Quadro: A cena inteira é dirigida por
window.__setFrame(frameIndex, timeSeconds, fps)ondet = frameIndex / fps. Cada posição, opacidade, contador e partícula é uma função matemática determinística det(usando um PRNG com semente comomulberry32, nuncaMath.random()). - Regra 2 — Revisão Visual Multimodal com Folha de Contato Antes da Renderização Completa: Antes de codificar o MP4 completo em 60fps, capture 8 a 12 timestamps-chave (
render.mjs --timestamps ...), costure-os em uma únicacontact-sheet.png(contact-sheet.py) e inspecione essa imagem usando sua ferramenta multimodal de Leitura/Visualização para corrigir recorte de texto, sobreposição ou baixo contraste. - Regra 3 — Áudio Preciso por Amostra + Pipe FFmpeg sem Bloat de Disco: Gere uma trilha sonora estéreo WAV multi-segmento + dicas de efeitos sonoros temporizadas (
synth-audio.py), depois transmita buffers PNG do Playwright diretamente para offmpeg -f image2pipe(render.mjs).
Fluxo de Trabalho do Agente Ponta a Ponta (6 Etapas)
Etapa 1: Storyboard e Orçamento de Cena
Projete uma tabela de linha do tempo concreta antes de escrever código. Agrupe o vídeo em cenas de 4 a 8 segundos com timestamps de transição explícitos (T_cut) que tanto scene.html quanto synth-audio.py compartilham:
| Cena | Tempo (t) | Quadros (60fps) | Foco Visual | Áudio / Dica SFX |
|---|---|---|---|---|
| 01 — Gancho / Alerta | 0,0s – 7,0s | 0 – 420 | Inicialização do terminal CRT, logs de máquina de escrever, clique no botão CTA em 2,7s | Pulso sub + dica de clique/destravamento da UI em 2,7s, subida até 3,4s |
| 02 — Métricas Heroicas | 7,0s – 15,0s | 420 – 900 | Grade synthwave em perspectiva 3D + 3 cartões de contadores com física de mola | Baixo synthwave completo 124 BPM + queda do arpejador estéreo em 7,0s |
| 03 — Telemetria Profunda | 15,0s – 23,0s | 900 – 1380 | Barras de progresso em tela dividida + medidor semicircular animado | Varredura de filtro + drive de chimbal, impacto sub em 15,0s |
| 04 — Chamada Final e Finale | 23,0s – 30,0s | 1380 – 1800 | Grade Bento de cartões de contribuidores + banner "JOB'S DONE!" e confete | Acorde final + dica de voz/SFX em 25,2s, fade-out mestre 28,5–30,0s |
Etapa 2: Crie scene.html com window.__setFrame(f, t, fps)
Escreva um arquivo HTML 1920x1080 autocontido usando HTML5 <canvas> (e/ou <svg> inline + sobreposições DOM) que exponha:
window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
if (window.__rafId) {
cancelAnimationFrame(window.__rafId);
window.__rafId = null;
}
const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
renderSceneAtTime(frameIndex, t);
};
- Sempre inclua um PRNG com semente (
mulberry32(seed)) para estrelas, partículas, confetes ou ruído, de modo que o quadrofseja idêntico bit a bit entre execuções. - Aguarde
document.fonts.ready(manipulado automaticamente pelorender.mjs). - Veja references/visual-patterns.md para receitas copiáveis e coláveis (grade de perspectiva 3D, contadores com mola, terminal CRT, medidores, cartões Bento, física de confete).
Etapa 3: Execute Snapshots Rápidos de Timestamps e Construa contact-sheet.png
Nunca execute uma renderização completa em 60fps primeiro. Amostre 1 a 2 timestamps por cena (mais pontos médios de transição) e construa uma única folha de contato:
# 1. Capture 9 keyframes PNG em ~3 segundos
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
--html ./scene.html \
--timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
--out-dir ./qa-frames
# 2. Costure-os em uma imagem de grade rotulada
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
--dir ./qa-frames \
--cols 3 \
--thumb-width 560 \
--title "FOLHA DE CONTATO DE QA VISUAL" \
--out ./contact-sheet.png
Etapa 4: Loop de Auto-Revisão Multimodal (Obrigatório!)
Chame sua ferramenta de Leitura/Visualização de imagem em ./contact-sheet.png (e em qualquer ./qa-frames/t-*.png individual que pareça denso). Verifique cada quadro contra a lista de verificação em references/visual-qa-loop.md:
- Algum texto transborda ou colide com bordas de cartão, crachás ou barras de progresso?
- Todos os números, rótulos e cabeçalhos HUD são de alto contraste e legíveis em 1080p?
- Cada transição de cena pousou limpa sem um quadro vazio/preto não intencional?
Se você notar qualquer problema em contact-sheet.png, corrija scene.html e execute a Etapa 3 novamente antes de prosseguir.
Etapa 5: Sintetize Trilha Sonora Processual e Misture Dicas SFX WAV
Gere uma trilha sonora estéreo WAV de 44,1 kHz cujas subidas de transição e dicas SFX correspondam aos timestamps exatos em scene.html:
python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
--duration 30.0 \
--bpm 124 \
--style synthwave \
--transitions 3.4,7.0,15.0,23.0,25.2 \
--cue "25.2:./sfx/jobs-done.wav:+1.5" \
--out ./soundtrack.wav
Para composições multi-segmento personalizadas ou integração de pacotes de som temáticos (como jblxo/claude-code-sound-packs), leia references/audio-synthesis.md.
Etapa 6: Renderize o MP4 H.264 Final em 60fps via Pipe FFmpeg
Depois que a revisão visual e a síntese de áudio passarem, execute render.mjs no modo pipe completo:
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
--html ./scene.html \
--duration 30 \
--fps 60 \
--audio ./soundtrack.wav \
--crf 18 \
--out ./final-video.mp4
Verifique o contêiner de saída com ffprobe:
ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4
Playbooks de Referência (Carregados Sob Demanda)
| Tópico | Arquivo de Referência |
|---|---|
| Primitivos visuais Canvas/SVG, funções de easing, PRNG com semente, grade synthwave 3D, medidores, cartões Bento | references/visual-patterns.md |
| Loop de QA visual multimodal com folha de contato, defeitos de layout comuns, estratégia de seleção de timestamps | references/visual-qa-loop.md |
| Síntese de áudio procedural com Python/NumPy, progressões de acordes, subidas, ducking, mixagem de efeitos sonoros WAV | references/audio-synthesis.md |