Anúncio Animado sobre Narração
Princípio
O que se ouve = o que se vê. A narração determina os tempos. Grava-se primeiro, o Whisper fornece o tempo de cada palavra, e cada texto, cena, notificação e efeito são inseridos sobre uma palavra. No código não há números de quadros: escreve-se at: 'clientes' e o tempo é extraído de public/words.json. Nova gravação = npm run vo, e o vídeo se ajusta sozinho.
Nenhum segundo na tela fica parado. Um segundo sem movimento = o espectador rola para frente.
Regras de Ferro
- Você não ouve. O proprietário do negócio é o único ouvido. Qualquer verificação de áudio da sua parte é numérica (
silencedetect,ffprobe, retranscrição). É proibido escrever "o áudio está normal" sem citar a saída. - Primeiro limpa-se silêncios, depois transcreve-se. O Whisper erra os tempos perto de silêncio. O
prep-vo.shfaz ambos na ordem correta. - Após alteração no áudio, execute
npm run vonovamente. Sem isso, toda a sincronização se desloca. - O vídeo termina quando a narração termina + 8 quadros (
DURATIONemtime.ts). Orender-all.shimprime a duração de cada arquivo em relação à narração. Se forem diferentes, algo foi cortado. - Texto apenas entre y=260 e y=1570. Acima e abaixo o Instagram cobre. O
validate()interrompe a renderização com explicação se o texto sair dessa área ou ultrapassar 1000px de largura. - Os efeitos ficam abaixo do áudio. Fixos em
Ad.tsx: narração 1.15, música 0.22, cada efeito é multiplicado porSFX = 0.38. "Efeitos altos" = alterar um número. - Still antes de MP4.
npm run checkrenderiza 10 quadros emout/stills. Olhe todos (leia os PNGs) antes da renderização completa. - Apenas conteúdo real. Números, pagamentos e mensagens de clientes: o que realmente aconteceu. É permitido ocultar nomes, proibido inventar resultados. Tanto pela política do Meta quanto porque as pessoas percebem falsificação.
- Hebraico: As fontes (Rubik, Heebo, variáveis, OFL) já estão no template e carregadas com
delayRender. A raiz está emdirection: rtl. Números dentro de um rótulo recebemdirection: ltr.
Instalação Inicial do Projeto
cp -R ~/.claude/skills/animated-voiceover-ad/template ~/ads/<nome-do-anuncio>
cd ~/ads/<nome-do-anuncio>
npm install
npm run setup # Efeitos e música do Mixkit
É necessário: Node 18+, ffmpeg, whisper-cli (brew install ffmpeg whisper-cpp) e o modelo whisper em ~/.whisper/models/ggml-large-v3-turbo.bin (se faltar, words.mjs imprime um comando de download).
O Pipeline
| Etapa | O que fazer |
|---|---|
| 1. Roteiro | Conforme references/script-formula.md. Cada frase é mapeada previamente para uma cena. Mostre ao proprietário antes de ele gravar. |
| 2. Gravação | No celular ou QuickTime, um único arquivo. Errou? Pare um segundo e recomece a frase. Depois, exclua a tomada ruim (veja references/audio.md). |
| 3. Limpeza e transcrição | npm run vo -- recording.m4a. Imprime todas as palavras com tempos. Mostre a transcrição ao proprietário e corrija palavras que o Whisper errou diretamente em public/words.json (apenas o w). |
| 4. Direção | Edite apenas src/Ad.tsx: KTS (texto cinético), notificações, SCENES. Cada tempo = palavra, ['ainda', 2] para segunda aparição. Detalhamento dos componentes em references/scenes.md. |
| 5. Verificação | npm run check (tsc + stills). Olhe todos os stills. |
| 6. Renderização | npm run render. Cada música em MUSICS (Root.tsx) = arquivo separado em out/, para teste A/B. |
| 7. Correções | Cada comentário do proprietário = uma alteração fixa: palavra diferente em at, volume, until. Não reescreva a cena inteira. |
Versões para Anúncios Pagos
- Música: Já embutida, 3 composições.
- Aberturas diferentes: Os 3 primeiros segundos determinam. Grave 2-3 hooks diferentes como arquivos separados, concatene cada um com o corpo usando
ffmpeg concat, executenpm run voem cada concatenação e renderize em pastas separadas. Todo oAd.tsxpermanece idêntico desde que as palavras do corpo sejam as mesmas. - Legendas completas:
CAPTIONS = trueemAd.tsx. Uma única linha, quebra por pontuação. Útil porque a maioria das visualizações em anúncios pagos é sem som.
Problemas Conhecidos
| Problema | Solução |
|---|---|
A palavra "X" não foi encontrada na narração | A mensagem sugere palavras próximas. Em hebraico, o Whisper cola ou separa prefixos (ו/ה/ל/ב). Use a palavra exatamente como está em words.json. |
| A renderização mostra código antigo | Bundle antigo em $TMPDIR/remotion-webpack-bundle-*. O render-all.sh o exclui. |
| TypeScript 7 instalado | Remotion precisa de [email protected]. |
delayRender trava | --timeout=180000 (já no render-all). |
| Carimbo encolhe antes de pousar | overshootClamping: true na sua spring (já implementado). |
| Palavras grudam após limpeza de silêncios | Aumente stop_duration no prep-vo.sh para 0.35. |
| Segundo "chato" | Adicione uma linha de KT, notificação ou efeito naquela palavra. Nenhum segundo sem evento. |
O Demo do Template
O template vem com uma narração de demonstração (voz TTS, public/vo.wav + public/words.json) e um Ad.tsx sincronizado a ela, para que se possa ver tudo funcionando antes de gravar: npm install && npm run setup && npm run check. Em um anúncio real: npm run vo -- recording.m4a substitui ambos, e então reescreva o Ad.tsx de acordo com o roteiro.