/motion — roteiro → vídeo de motion graphics com narração
Entrada: um roteiro (texto colado ou arquivo .txt/.md/.docx). Não há vídeo de câmera: tudo são cenas animadas em tela cheia.
Saída: <pasta>/<NOME>_MOTION/ com <NOME>.mp4 (H.264 + AAC, −14 LUFS), <NOME>.srt, <NOME>_premiere.xml (projeto editável), Assets/{Cenas,Legendas,Overlay,Narracao,Musica,SFX}, LEIA-ME.md e .work/ (persistente, permite fazer v2).
Fale com o usuário em português brasileiro, mas mantenha a naturalidade. Avise o progresso entre etapas longas.
Caminhos: SK = pasta desta skill (Claude Code: ~/.claude/skills/motion; Codex: ~/.codex/skills/motion).
PY = o Python da skill: $SK/.venv/bin/python -I (Windows: $SK\.venv\Scripts\python.exe -I). Use-o para todos os scripts .py.
Catálogo de cenas: $SK/reference/cenas.md · exemplo completo: $SK/reference/exemplo/ (script.json + story.js).
Se doctor.py marcar algo com ✗: bash $SK/scripts/install.sh (Windows: powershell -ExecutionPolicy Bypass -File $SK\scripts\install.ps1).
0 · Perguntas iniciais (SEMPRE, antes de produzir)
Leia primeiro o roteiro e $PY $SK/scripts/brand.py list (marcas salvas). Depois pergunte tudo junto em uma única rodada (no Claude Code com a ferramenta AskUserQuestion; no Codex ou outros, uma única mensagem numerada). Não pergunte o que o usuário já disse.
- Voz — Feminina ou Masculina. Por padrão argentina (edge-tts:
es-AR-ElenaNeural/es-AR-TomasNeural). Se o usuário pedir outro sotaque, use a voz daquele país (tts.py voices eslista todas: es-UY, es-MX, es-ES, es-CL, es-CO…). Se tiverELEVENLABS_API_KEYe quiser mais realismo, ofereça ElevenLabs (tts.py voices eleven argentine). - Marca — uma das salvas (mostre os nomes) ou Marca nova.
- Formato — Vertical 9:16 (Reels/TikTok/Shorts, padrão) · Quadrado 1:1 · 4:5 (feed) · Horizontal 16:9 (YouTube).
- Música — Energética (Upbeat 110–140 BPM) · Calorosa/inspiradora (Medium 90–110) · Corporativa/tranquila · Tenho minha música (peça o caminho).
Se for marca nova, segunda rodada (também tudo junto):
- Nome da marca e logo (caminho para PNG/SVG, ou "sem logo") e usuário de redes (ex.
@consultorio). Se der o logo:$PY $SK/scripts/brand.py colors <logo>e proponha a paleta a partir dessas cores. - Cores — opções: Extrair do logo · Preto + laranja (editorial) · Azul profundo + celeste (saúde/confiança) · Verde + creme (bem-estar); ou hex próprios. São necessárias 4:
dark(fundo escuro),light(fundo claro),accent(destaque principal),accent2(secundário, opcional). - Tipografias —
brand.py fontslista combinações: Editorial condensada · Moderna geométrica · Impacto · Elegante (ou qualquer família de Google Fonts pelo nome). - Estilo — legendas sim/não (padrão sim), decoração de fundo: grão + grade + manchas de cor (padrão) · anéis · pontos · limpo.
Crie
$SK/brands/<slug>/brand.jsoncopiandobrands/editorial/brand.json(em cada tipografia deixe apenasfamily,weight, e para títulosupper/stretch/tracking/leading; para destaqueitalic), coloquelogocom o caminho absoluto e execute$PY $SK/scripts/brand.py setup <slug>(baixa as fontes, copia o logo, verifica contraste: corrija os ⚠️). Mostre a amostra:node $SK/scripts/render.js --brand-preview=<slug> --out=<work>/marca.jpg --format=<formato>→ veja a imagem e mostre ao usuário; confirme antes de prosseguir (é rápido de ajustar). A marca fica salva para a próxima.
1 · Preparação
NOMEem MAIÚSCULAS_COM_HÍFENS a partir do tema. Pasta: a do arquivo de roteiro, ou o diretório de trabalho se foi colado.work=<pasta>/<NOME>_MOTION/.work.$PY $SK/scripts/timing.py start "<work>"(cronômetro) e$PY $SK/scripts/doctor.py.config.json:
{ "name": "NOME", "out_dir": "/abs/<pasta>/NOME_MOTION", "edit_dir": "/abs/<pasta>/NOME_MOTION",
"format": "9:16", "fps": 30, "brand": "<slug>", "tail": 1.6, "keywords": ["palavra","chave"], "sfx_max": 6,
"music": {} }
keywords = 3–6 palavras do roteiro que são destacadas nas legendas. Opcionais: "captions": false, "logo_corner": false.
2 · Roteiro → beats → narração
O roteiro é do usuário: não reescreva o conteúdo. Apenas divida e ajuste a pronúncia.
- Divida em beats (1 frase ou ideia, 2–6 s cada um; 10–18 beats para 1 minuto). Cada beat geralmente é uma cena.
say(opcional) = como pronunciar quando o texto escrito confunde a voz: números grandes ("70 %" → "setenta por cento"), siglas ("OMS" → "o eme esse"), símbolos, anos, abreviações.textpermanece como está escrito.pause= silêncio após o beat (padrão 0,38 s se terminar em ponto/pergunta, 0,18 s se não). Mais pausa (0,6) antes de um remate ou do CTA.<work>/script.json:{"voice":{"engine":"edge","id":"es-AR-ElenaNeural","rate":"+5%"},"lead":0.35,"target":60,"beats":[{"id":"b01","text":"…"},…]}$PY $SK/scripts/tts.py "<work>"→voice.wav+words.json(tempo de cada palavra) e a duração. Duração alvo ≈ 60 s:- mais de 66 s → aumente
rate(máximo+15%); se ainda passar, proponha cortes concretos ao usuário e aguarde resposta. - mais curta → está ok, não estique o roteiro (pode diminuir
rateaté-5%se soar apressada).
- mais de 66 s → aumente
- Ouça mentalmente o ritmo: se um beat ficar muito longo (> 7 s), divida-o. Apenas os beats que mudam são regenerados (cache).
3 · Música
- Se o usuário forneceu música:
"music": {"path": "/abs/tema.mp3", "offset": 0}. - Se não, Envato (sempre instrumental):
$PY $SK/scripts/envato.py search "<work>" music "<estilo em inglês>" --mood <mood> --tempo "<tempo>" [--genre <gênero>]. Escolha pelo tom e pelo perfil de energia (constante, sem quedas longas no primeiro minuto) e$PY $SK/scripts/envato.py use "<work>" music <busca>#<n>. Coloqueoffset(segundo onde entra a parte com energia; veja o perfil ▁▂▃█). - Níveis automáticos no mix.py: mais forte antes da narração (
intro−8 dB), abaixa abaixo da narração (bed−21 dB), sobe na cauda (outro−10 dB) e fade final. Ajustáveis emconfig.music. - A prévia do Envato tem marca d'água: na entrega avise que é necessário licenciá-la. Com navegador com sessão do Envato: peça confirmação uma vez, licencie com o nome do vídeo e baixe em WAV; se não, dê o link ao usuário. Depois
$PY $SK/scripts/envato.py collect "<work>"e execute novamente apenasmix.py(não precisa re-renderizar).
4 · Storyboard → <work>/story.js
Baseie-se em reference/cenas.md e reference/exemplo/story.js. Uma chamada S(tipo, inicio, params) por cena, em ordem:
inicio: id do beat ('b03') ouw('palavra')(começa nessa palavra). A cena dura até o início da próxima; a primeira começa em 0.- Dentro de params, todos os tempos internos são sincronizados com a narração usando
w('palavra')(ouw('palavra', 1)para a 2ª ocorrência): itens de lista, contagens, selos, mensagens, botão do CTA. - Comuns a todas:
bg('dark'|'light'|'accent'|'accent2'; se omitido alterna automaticamente),tr('wipe'|'slide'|'circle'|'push'|'zoom'|'cut'; se omitido rotaciona),cap:false(sem legendas),sfx(null= sem som ·'pop'·[['ding',1.2]]). - Helpers de texto:
H('texto')= destaque em caixa colorida ·A('texto')= texto na cor de destaque.
Critério de direção (obrigatório):
- Gancho nos primeiros 2 s:
question,bigword,kineticoutitleforte, em fundoaccent. A primeira mudança de cena antes dos 3–4 s. - Ritmo: uma cena a cada 3–5 s (12–18 cenas por minuto). Nada parado por mais de ~5 s: se a cena for longa, que ela se construa (itens sincronizados).
- Variedade: não repita o tipo de cena seguido; máximo 2
kineticseguidas; alterne cenas de texto com gráficas (stat,bars,donut,icons,steps,compare,phone). - Mostrar, não repetir: o texto na tela são palavras-chave, dados e estrutura, não a frase inteira (exceto
kinetic/quote, que mostram a frase enquanto é dita e desligam as legendas). - Dados →
stat/bars/donut. Enumerações →list/steps/icons. Contrastes (mito/realidade, antes/depois) →compare. Perguntas →question. Conversas/mensagens →phone. Remates →bigword. Fotos do usuário →image. - Encerramento com
cta(seguir / comentar uma palavra / salvar / link) sincronizado com o que o roteiro diz. - Textos curtos: títulos de 1–3 palavras por linha, itens de ≤ 6 palavras.
5 · Planejar, testar e renderizar
node $SK/scripts/render.js "<work>" --plan→ cenas com tempos, SFX e avisos de Direção. Corrija todos os ⚠️ e repita.node $SK/scripts/render.js "<work>" --test --at=0.3,mid,end→<work>/sheet.jpg(3 quadros por cena: entrando, no meio, montada). Olhe a folha e corrija: textos que encolhem demais (aviso "encolheu para N %"), cortes, sobreposições com legendas, cores com pouco contraste, cenas vazias no meio (o conteúdo precisa aparecer rápido).- Render final (em segundo plano, ~1 min por minuto de vídeo):
node $SK/scripts/render.js "<work>"→<work>/video.mp4. $PY $SK/scripts/mix.py "<work>"→<NOME>.mp4+<NOME>.srtemout_dir.- Projeto para Premiere (padrão sempre; pule apenas se
config.premiereforfalse):node $SK/scripts/render.js "<work>" --premiere(em segundo plano, ~2–3 min) e$PY $SK/scripts/build_xml.py "<work>". Pistas: V1 cenas (um por clipe, com a transição de entrada já composta) · V2 legendas com alfa · V3 logo · A1 narração (uma frase por clipe) · A2 música com keyframes de volume · A3+ SFX. Marcadores por cena. - Veja 3–4 quadros do MP4 final (
ffmpeg -ss <t> -i <mp4> -frames:v 1 x.jpg) para confirmar.
6 · Entrega
$PY $SK/scripts/timing.py report "<work>".LEIA-ME.mdemout_dir: como abrir no Premiere (Arquivo → Importar →<NOME>_premiere.xml; não mova nem renomeie a pasta; tabela de pistas; o que se edita ali — cortar/mover/excluir cenas, reajustar frases da narração, trocar música e volumes, remover SFX, usar o.srtcomo legendas nativas — e o que não: o texto dentro de cada gráfico, que se altera pedindo ao Claude), voz usada, marca, formato, duração, estrutura (tabela cena → texto → tempo), música (comenvato.py reporte se falta licenciar), SFX, tempo de processamento, como pedir alterações.- Responda curto: caminho do MP4 e do XML, duração, voz e música escolhidas (avise se a música é prévia não licenciada), cenas destacadas, tempo total.
Versões (v2, ajustes)
Reutilize .work: altere script.json (voz/texto: apenas os beats tocados são regenerados) e/ou story.js, aponte out_dir para <NOME>_MOTION_v2 e repita a partir da etapa correspondente (mudança de música ou volume → apenas mix.py + build_xml.py; mudança visual → render + mix + render.js --premiere --only=<n.º da cena> + build_xml.py; mudança de texto → tts + tudo).
Alterar um texto de um gráfico já importado no Premiere: edite story.js e execute render.js --premiere --only=N (re-renderiza apenas essa cena com o mesmo nome de arquivo), o MP4 se desejar, e avise ao usuário que no Premiere clique com o botão direito no clipe → Substituir/Vincular mídia (ou feche e reabra o projeto) para ver a mudança. Se a duração da cena mudar, regenere o XML e reimporte. Cenas novas: adicione-as a engine/engine.html seguindo cenas.md.
Notas técnicas
- Camadas para Premiere: cenas em ProRes 422 HQ (opacas); legendas e logo em ProRes 4444 com alfa. O áudio no Premiere fica ~2 dB mais baixo que o MP4 (o MP4 leva uma normalização final a −14 LUFS).
- Motor:
engine/engine.htmlrenderizado quadro a quadro com Chrome (puppeteer-core) em paralelo, H.264 yuv420p. Todas as cenas são funções puras do tempo. - O conteúdo de cada cena é escalado automaticamente para caber na área segura (por formato) sem transbordar; se encolher muito, avisa.
- SFX: usa a biblioteca da skill
edicaose estiver instalada (ouassets/sfxprópria com o mesmocatalog.json); se não houver sons, continua sem eles. - Voz: edge-tts usa o serviço de voz do Microsoft Edge (requer internet, sem chave). ElevenLabs:
{"engine":"eleven","id":"<voice_id>"}+ variávelELEVENLABS_API_KEY. - Não use
rm -rfcom globs relativos.