Communitygithub.com

Opus Visual Motion Engine

Pipeline disciplinado para motion graphics: vídeo/UI renderizado por código, seek(t) determinístico, QA automatizado de render, exportação MP4 — funciona para modelos de texto puro.

O que é Opus Visual Motion Engine?

O Opus Visual Motion Engine é um pipeline disciplinado para produção de vídeos e páginas animadas, projetado para funcionar mesmo com modelos de linguagem que não conseguem visualizar imagens. Ele segue um processo rigoroso de planejamento → construção a partir de templates → renderização → QA automatizado → correção → exportação. O pipeline é determinístico: toda a animação é dirigida por uma função `render(t)` que recebe o tempo em segundos e retorna o mesmo quadro independentemente do estado anterior, garantindo repetibilidade e previsibilidade. Ele suporta plataformas como Claude Code, Cursor, Codex e outros agentes de IA, e inclui ferramentas de QA que geram relatórios detalhados, contact sheets e verificações de conformidade com regras de design, acessibilidade e performance. O sistema também lida com sincronização de áudio a partir de dados extraídos de arquivos de música ou voz, permitindo que a animação reaja a batidas, onsets e níveis de frequência.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add Lob0Garou/opus-visual-motion-engine

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que Opus Visual Motion Engine faz?

Um pipeline disciplinado para entregáveis visuais: planejar → construir a partir do template → renderizar → QA → corrigir → exportar. A qualidade vem das portas aplicadas antes e depois da renderização, não do gosto. Siga as etapas em ordem. Não pule uma etapa porque a tarefa "parece simples".

Os caminhos abaixo são relativos ao diretório desta skill (a base skill_resources que você recebeu). Chame-o de $SKILL.

0. Leia primeiro (incondicional)

Antes de escrever qualquer código, leia as referências que correspondem ao entregável. Elas são autoritativas para o tópico:

EntregávelLeia
vídeo, motion graphic, explicador, vídeo de produtoreferences/video-generation.md, references/motion-design.md, references/javascript-animation.md
tipografia cinética / peça liderada por tipoo conjunto de vídeo acima + references/typography.md
landing page, dashboard, mockup, UIreferences/visual-design.md, references/typography.md
diagrama, esquema, visualização de dadosreferences/visual-design.md §4
decisões de enquadramento / câmerareferences/cinematography.md
durações e easingsreferences/animation-primitives.md
música ou voz para sincronizarSKILL.md §10 + references/video-generation.md §6

Exemplos trabalhados estão em examples/*.md. Leia o mais próximo do briefing.

1. Planeje antes do código (escreva-o)

Escreva o plano em sua resposta (ou em um PLAN.md ao lado da saída) antes de criar o HTML. Um plano que existe apenas em sua cabeça não conta.

UI / página

  1. Mensagem principal: uma frase. O que o espectador deve entender em 3 segundos?
  2. Direção nomeada: um nome, 4–6 tokens hexadecimais nomeados com significados atribuídos, tipografia com papéis, tratamento de forma. Derive do setor do assunto, materiais e linguagem. Uma loja de brinquedos e um dashboard fintech nunca compartilham uma direção.
  3. Hierarquia: marque cada bloco como PRIMÁRIO / SECUNDÁRIO / TERCIÁRIO. Apenas o PRIMÁRIO recebe o único gesto ousado.
  4. Progressão de seções: uma linha por seção, dando seu trabalho e como ela faz a transição para a próxima.
  5. Matemática pré-render: largura do texto ≈ chars × 0.55 × font-size (sans) ou × 0.5 (serif); largura da caixa = max(title_chars × 8, subtitle_chars × 7) + 24 a 14px; encaixe de linha = Σlarguras + gaps ≤ contêiner. Trace cada conector contra cada caixa. Se cruzar um, roteie um caminho em forma de L.

Vídeo / motion graphic

  1. Mensagem central: uma frase. Se precisar de duas, são dois vídeos.
  2. Batidas: 3–7. Cada batida responde "o que o espectador agora sabe?"
  3. Cartão de cena por batida: início/fim (s), composição, câmera, tamanhos de tipo, primitivas (2–4), saída. Use o template em references/motion-design.md §2.
  4. Momento de assinatura: nomeie o ÚNICO quadro onde o mecanismo é mostrado, não rotulado (ex.: ruído filtrado em sinal). Se a história só funciona com suas legendas, redesenhe a batida.
  5. Linha do tempo global: timestamps absolutos. A SAÍDA de uma cena é concluída antes da próxima cena reivindicar o espaço. Defina DURATION para o verdadeiro fim (10–20s por padrão; 30–45s apenas com narração).

Uma cena sem cartão não pertence ao vídeo.

2. Construa a partir do template (vídeo)

Copie assets/composition-template.html ao lado do entregável e preencha os blocos EDIT. Não reescreva os blocos ENGINE. Eles já fornecem:

  • um #stage 1920×1080 (altere STAGE_W/H para 1080×1920 ou 1080×1080), ajustado a qualquer janela;
  • window.DURATION, window.seek(t), window.render(t), window.SCENES: o contrato de captura/exportação (QA captura cada cena de SCENES);
  • at(), ease.*, lerp, mulberry32 (PRNG seedado) e layer() para visibilidade de cena mais SAÍDA;
  • auxiliares de áudio audioAt(t, "rms"|"low"), since(t, list), hit(t, list, dur) que leem window.AUDIO (§10) e retornam 0 sem ele;
  • um player de pré-visualização (espaço, ←/→, Home/End) que desliga automaticamente sob captura e movimento reduzido;
  • tokens de cor nas 3 camadas necessárias (claro, protegido por prefers-color-scheme, [data-theme]).

Para páginas, escreva um único arquivo HTML normal seguindo §6.

3. Tempo determinístico (vídeo)

  • render(t) é o único motor de estado. Cada posição, opacidade, tamanho, número e dashoffset é computado a partir de t em segundos. seek(x) renderiza o quadro idêntico independentemente do que foi renderizado antes.
  • t está em segundos. Mantenha t em [0, DURATION], nunca em [0, 1]: prender segundos a 0..1 congela silenciosamente toda a linha do tempo.
  • Proibido: setTimeout, setInterval, animações/transições CSS como linha do tempo, Math.random() não seedado, Date.now() no estado. requestAnimationFrame só pode avançar o relógio de reprodução e chamar render(clock). O template já faz isso.
  • Aleatoriedade: gere em tempo de construção a partir de mulberry32(seed), nunca dentro de render.
  • Desenho SVG precisa de todos os três: pathLength="1", stroke-dasharray="1" e stroke-dashoffset de 1 a 0. Sem um dasharray, a linha aparece totalmente desenhada desde o quadro 0.
  • inline-block em spans de palavras engole espaços finais. Coloque espaçamento em margin-right.

4. Gramática de movimento

Cinco movimentos, cada um com um trabalho. Se um movimento não é nenhum destes, delete-o.

  • ENTRADA: uma sequência orquestrada por página ou cena, em ordem de leitura, irmãos escalonados em 60–120ms. Fade-up em toda seção é a marca registrada de IA.
  • ÊNFASE: um elemento de cada vez: um aumento de escala (≤1.2), um brilho, ou uma mudança de cor que carrega significado.
  • TRANSIÇÃO: uma mudança de estado. A parte mudada se move; todo o resto permanece parado. 0.2–0.6s.
  • CÂMERA: uma escala/translação no nível do stage, no máximo uma vez por cena, 0.8–1.2s, nunca durante a leitura de texto.
  • SAÍDA: 0.3–0.5s, completamente concluída. Nenhum elemento sobrevive em meio-estado através de um limite de cena, exceto uma âncora de continuidade deliberada que persiste identicamente ou morfoses (o mesmo objeto mudando de estado, que é a transição mais forte disponível).

Transições carregam significado: corte duro = mudança de categoria, morph = mesma coisa mudando, pan = travessia. Nunca um crossfade padrão em todo lugar. Durações e easings estão em references/animation-primitives.md. Vizinhos que se movem juntos recebem durações diferentes ou um deslocamento.

5. Decisão de stack

SituaçãoStack
micro-movimento de páginaTransições CSS em transform/opacity, 0.2–0.6s; loops ≤2s dentro de @media (prefers-reduced-motion: no-preference)
vídeo / motion graphic / tipografia cinéticatemplate + vanilla render(t) (padrão)
>6 faixas escalonadas ou orquestração de morph SVGGSAP UMD fixado, UMA linha do tempo mestre pausada, seek(t) → tl.seek(t)
gráficosSVG inline (padrão) ou Chart.js UMD com animation:false, cores hexadecimais (canvas não pode ler variáveis CSS)
arte generativap5.js com randomSeed/noiseSeed
3D, apenas quando 3D é a mensagemThree.js UMD fixado; câmera roteirizada em render(t)

Use o stack mais simples que atinja o resultado. Scripts externos devem ser versões exatas fixadas de cdnjs.cloudflare.com ou cdn.jsdelivr.net. Embuta todo o resto. Cada fonte recebe um stack de fallback real.

6. Piso técnico (não negociável)

  1. Único .html com CSS e JS inline, abaixo de 16 MB, imagens/dados como URIs data:.
  2. Cores como tokens :root; camada escura sob @media (prefers-color-scheme: dark) protegida por :root:not([data-theme="light"]) e repetida sob :root[data-theme="dark"]; fundo body explícito.
  3. meta viewport com viewport-fit=cover; env(safe-area-inset-*) no padding; height:100% em html/body, nunca 100vh; blocos largos rolam dentro de seu próprio overflow-x:auto; grids usam minmax(0,1fr).
  4. Números computados exibidos passam por Math.round, toFixed ou Intl.NumberFormat. Contagens pousam exatamente no valor final.
  5. Acessibilidade: contraste ≥4.5:1 (≥3:1 para texto ≥24px), foco visível, prefers-reduced-motion respeitado (o template mostra o quadro final estabilizado).
  6. Tipografia legível: em um quadro de vídeo 1080p, nenhum texto abaixo de 20px (H/54). Em páginas móveis, nenhum texto do corpo abaixo de 14px.
  7. Armazenamento do navegador nunca retém estado da linha do tempo. Onde o armazenamento é usado, envolva-o em try/catch.

7. Evite design genérico de IA

Onde o briefing deixa liberdade, nunca gaste-a nesses padrões (qa.mjs sinaliza vários automaticamente):

Marca registradaCorreção
creme #F4F1EA-ish + serifa display + acento terracota #D97757-ishuma paleta tirada dos próprios materiais do assunto
quase-preto + um acento ácido, usado independentemente do assuntopermitido apenas quando a direção justifica por escrito
cards idênticos arredondados, um raio em todo lugar, a mesma sombra suavetokens de raio por hierarquia; apenas objetos limitados por card
gradientes como decoração, gradientes roxos, glassmorfismopreenchimentos planos; no máximo um gradiente, apenas para uma propriedade física contínua
sobrancelhas em ALL-CAPS com tracking, strings de meta com ponto médio, "→" em linksletras minúsculas; delete rótulos que repetem o conteúdo
Inter / fonte do sistema por padrãotipografia escolhida para este assunto, com um stack de fallback
uma única palavra acentuada em um títulopermitido APENAS quando a cor de acento é um token semântico usado para o mesmo significado em outro lugar na peça (ex.: coral = ruído)
herói genérico: título + subtítulo + CTA + screenshotcomece com a coisa mais característica no mundo do assunto
tudo centralizado, a mesma grade em cada seçãoum sistema de alinhamento por seção; varie o ritmo
tudo animando ao mesmo tempo, 300ms em todo lugaro mapa de duração + escalonamento (§4)

Gaste ousadia em um lugar, depois remova um acessório.

8. Render + QA (obrigatório antes de entregar)

Execute o QA automatizado. Ele renderiza o arquivo headless e escreve evidências mais um veredito. Precisa de Node ≥18. A primeira execução em uma cópia nova da skill precisa de npm install em $SKILL/scripts (pule se scripts/node_modules existir).

node "$SKILL/scripts/qa.mjs" caminho/para/entregavel.html

No DSH no Windows, execute-o com a ferramenta pwsh usando o mesmo comando. Opções: --step 0.25 (uma grade mais fina para cenas rápidas), --out <dir>, --mode page|video.

Modo vídeo (automático quando DURATION + seek existem) captura um quadro a cada passo e verifica: APIs proibidas, determinismo em revisitas fora de ordem, uma linha do tempo congelada, ar morto, spans quase vazios, um quadro final instável, colisões de texto, texto sobre outros gráficos, clipping, contraste, tamanho mínimo de tipo, linhas dash-offset que nunca desenham, loops de movimento reduzido, erros de console/página e marcas registradas do template. Modo página renderiza desktop 1440, mobile 390 e esquema escuro, e verifica as mesmas regras de layout além de transbordo horizontal móvel.

As saídas vão para qa-<nome>/: report.md (veredito e descobertas), report.json (cobertura de tinta por quadro e mudança), contact-sheet.png (cada quadro em uma imagem), moments.png (entrada, meio e fim de cada cena, retirados de window.SCENES), key_000..100.png e frames/.

  • Passe o momento de assinatura e qualquer ponto de sincronização explicitamente: --at 5.4,9.1.
  • Camadas deliberadas (tipo cinético empilhado intencionalmente, um título sobre filmagem) vão dentro de um elemento com data-qa-allow-overlap. Isso pula as verificações de colisão e texto-sobre-gráficos apenas para aquela subárvore. Nunca use para silenciar uma colisão acidental.
  • Um WARN font significa que a família de primeira escolha não carregou e o texto está em um fallback. Corrija antes de julgar layout, porque toda largura está errada.

Código de saída 0 = nenhum FAIL. FAIL é bloqueante. Cada WARN é corrigido ou justificado em uma linha em sua crítica.

9. Loop de crítica

  1. Se seu modelo pode ler imagens: abra contact-sheet.png, depois qualquer key_*.png que parecer errada. Julgue os pixels, não suas intenções.
  2. Se seu modelo é apenas texto: use report.md mais a tabela por quadro em report.json. coverage < 0.015 significa que o quadro parece vazio. Um diff de 0 através de uma cena significa que nada se move. Um pico em diff marca um corte. Verifique cruzadamente cada cartão de cena com timestamps contra esses números.
  3. Responda cada pergunta com uma observação concreta, não "✓":
    • Composição: em cada quadro-chave, onde o olho pousa primeiro? Isso é a mensagem?
    • Hierarquia: o PRIMÁRIO é inconfundível? Há exatamente uma coisa em movimento que importa por quadro?
    • Mecanismo: o momento de assinatura mostra a ideia com as legendas removidas?
    • Continuidade: todas as transições estão limpas, sem nada em meio-estado em um limite e âncoras idênticas ou morfando?
    • Tempo: há deslocamentos presentes, sem durações padrão, e tempo de leitura ≥1.2s por 8 palavras?
    • Tipografia / contraste / densidade: tamanhos conforme o plano, ≤5 elementos concorrentes por quadro, legível no modo escuro?
    • Narrativa: um espectador poderia repetir a mensagem central após uma assistida?
  4. Corrija → reexecute qa.mjs → re-critique. Repita até QA passar e a crítica não ter item aberto.
  5. Pergunta final, respondida honestamente: "Isso parece intencionalmente projetado, ou meramente gerado?" Se "gerado": nomeie o que é genérico, revise o plano (§1) e reconstrua. Uma primeira renderização quase nunca é o entregável. Espere 2–3 gerações.

10. Sincronização de áudio (quando há música ou voz)

Nunca adivinhe o tempo pelo ouvido. Transforme o áudio em dados e deixe render(t) lê-los:

node "$SKILL/scripts/audio-data.mjs" music.mp3 --inject composition.html   # escreve window.AUDIO no HTML
  • AUDIO.beats (uma grade uniformemente espaçada no tempo estimado), AUDIO.onsets (batidas, notas, sílabas) e por quadro AUDIO.rms / AUDIO.low (0..1; low é a banda de kick/baixo <150 Hz).
  • Dirija o movimento com os auxiliares do template: hit(t, AUDIO.beats, 0.2) para um pulso de batida (ÊNFASE), audioAt(t, "low") para escala reativa ao kick, since(t, AUDIO.onsets) para revelações por batida. Coloque cortes de cena nas batidas: escolha inícios de cena de AUDIO.beats.
  • A sincronização é exata ao quadro por construção: um pulso pousa no primeiro quadro em ou após sua batida (≤1 quadro, ≤33 ms a 30 fps). Se o áudio começar depois de t=0, passe --offset <s>.
  • Os níveis são verificados antes de alguém ouvir. Amostras cortadas saem com código 1. Um pico de amostra acima de −1 dBFS avisa, porque a codificação AAC vai cortá-lo. Volume fora de −18..−12 LUFS é relatado (plataformas normalizam para cerca de −14).
  • --bpm substitui a estimativa automática.
  • Um arquivo inalterado usa --dry-run --print para inspecionar beats, onsets, níveis RMS e frequências sem modificar o HTML.

Habilidades Relacionadas