O que Vertical Reels Video Studio (pro) faz?
End-to-end: (primeira execução: pergunte pelo handle/watermark/CTA/voz do usuário) → tópico → pesquisa → rascunho → aprovação → narração → timing → cenas Remotion → render → exportação Reels → QA → capas + legendas → entrega.
Esta é a versão mais completa de vertical-reels-video-studio (básico). A configuração da marca fica em brand.config.json (lido por src/brand.ts e passado para as composições como a prop brand).
0a. Primeira execução: pergunte ao usuário PELAS CONFIGURAÇÕES DELE (nunca use padrões)
Antes do primeiro vídeo, se brand.config.json estiver faltando, tiver "configured": false ou ainda contiver @yourhandle,
pergunte ao usuário (uma pergunta por vez) e salve as respostas em brand.config.json:
- Handles sociais: Instagram, Threads, TikTok, X (quais ele usa).
- Texto da marca d'água (exatamente como deve aparecer, ex.
@yourhandleou@ig / @x) e posição (bottom-center,bottom-left,top-left,top-right). - CTA texto e o handle mencionado.
- Voz: o ID da voz ElevenLabs + modelo + idioma, ou "Vou gravar minha própria voz". A chave da API é solicitada apenas como segredo
ELEVENLABS_API_KEY. - Idioma e tom; como a voz deve dizer o nome/handle dele.
Em seguida, defina "configured": true. Nunca invente um handle, nunca reutilize o de outra pessoa (incluindo o autor deste kit) e nunca renderize uma marca d'água que ainda diga @yourhandle.
0b. Configuração da marca (brand.config.json, preenchido pelas respostas do usuário)
| Chave | Placeholder | Notas |
|---|---|---|
| Handles | {{IG_HANDLE}}, {{THREADS_HANDLE}}, {{TIKTOK_HANDLE}}, {{X_HANDLE}} | handles.*, do próprio usuário |
| Marca d'água | {{WATERMARK}} + posição | watermark.text / watermark.position, texto exato fornecido pelo usuário; nunca codificar em cenas |
| Idioma / tom | {{LANGUAGE}}, {{TONE}} | ex. indonésio casual gua/lu, emoji esparso |
| Nome falado | {{SPOKEN_NAME}} | Como a voz deve dizer seu handle (ex. "Jane Doe" para @janedoe_). As legendas ainda mostram o handle real |
| Aviso legal | {{DISCLAIMER}} | Para tópicos financeiros, ex. "Educação, não é conselho financeiro" |
| Voz | {{VOICE_ID}}, {{TTS_MODEL}}, {{LANGUAGE_CODE}} | voice.*, escolha do usuário (ou sua própria gravação) |
| Chave da API | env ELEVENLABS_API_KEY | Nunca imprimir, registrar ou commitá-la |
| CTA | {{CTA}}, {{CTA_HANDLE}} | cta.text / cta.handle, perguntado ao usuário (ex. "Siga {{CTA_HANDLE}} para mais", "Comente TUTORIAL") |
| Regras rígidas | {{HARD_RULES}} | Marcas a nunca ridicularizar, nomes a borrar, palavras a nunca dizer |
| Dispositivo de render | {{RENDER_DEVICE}} | Máquina GPU ou CPU. Sempre reportar qual foi realmente usado |
1. Pesquisa e rascunho (sem áudio, sem render)
- Verifique cada afirmação com fontes primárias: documentos oficiais/PRs, postagem do próprio autor, registros, capturas de tela datadas. Postagens de executivos contam como declarações oficiais. Rotule estimativas (
ESTIMATE · não oficial) e alegações (ALLEGED). Descarte o que não puder verificar em vez de suavizar. - Uma história por vídeo, palavras do dia a dia, ritmo lento. Nomes de produtos difíceis vão na tela, não na narração.
- Ofereça 2–4 opções de gancho (H1, H2, …): uma pergunta por que/como ou um contraste ousado. Deixe o usuário escolher.
- Tabela com tempo:
tempo | na tela | VO. Alvo 45–65 s, máximo rígido 90 s (mire ≤ 88 s para que uma revisão ainda caiba). - Escreva
factcheck.md(afirmação → fonte → status) esources.md. - Envie o rascunho e aguarde aprovação. "Não renderize" do usuário é final até que ele diga para prosseguir.
2. Narração (ElevenLabs)
- Dois scripts:
script-display.txt(o que as legendas mostram) escript-tts.txt(soletrado para a voz). Mantenha um mapa display↔TTS. - Pronúncia (veja
docs/VOICEOVER.md):A.I.com pontos para soar em inglês; tickers letra por letra em VO não-inglês (ETH →E, T, H); números como palavras; termos em inglês com ortografia inglesa simples (sem hifenização); uma vírgula após um /t/ final antes de uma vogal; nomes de marcas soletrados novamente apenas quando testes provarem que ajuda. - Pós-processamento
atempo1.05 (1.1 para conteúdo rápido). Loudness −14 LUFS integrado, ≤ −1 dBTP. - Sem linhas duplicadas. Se uma linha repetir o gancho ou uma batida anterior, corte ou reformule.
- Verifique a cota de caracteres primeiro. Regrave apenas linhas com falha (passe
previous_textpara continuidade).
3. Timing
- Carimbos de tempo das palavras do alinhamento TTS (dividir pelo fator de tempo) ou faster-whisper →
timing.json{duration, phrases:[{s,e,words:[{w,s,e}]}], scenes:[{id,start}]}(scripts/build-timing.py). - Mescle tokens soletrados novamente para palavras de exibição (
A.I.→AI,E, T, H→ETH) ou as legendas começam atrasadas. - Cenas dependem das palavras faladas:
wt(scene, word)→ quadro onde aquela palavra começa.
4. Estilo de movimento (Remotion, 1080x1920, 30 fps)
Visual: fundo #0A1016, creme #EFE6D2, âmbar #FFB000, vermelho #E2553F, verde #7BD88F. Fontes via @remotion/google-fonts: Big Shoulders 800 (títulos), Plus Jakarta Sans (corpo/legendas), JetBrains Mono (chips/código).
Layout: conteúdo importante y 200–1500. Cluster do rodapé: legendas karaokê ~y 1310–1353, marca d'água (se o usuário escolheu embaixo) ~y 1427–1446, progresso ~y 1474, todos à esquerda de x 960 (Reels desenha seus botões à direita).
Sem quadros vazios: o gancho é legível no quadro 0; a abertura e o fechamento são tão completos quanto o meio (uma imagem herói, o apresentador, um chip), nunca uma linha solitária em um fundo em branco.
Auxiliares de easing (src/motion/ease.ts):
const clamp01=(x:number)=>Math.max(0,Math.min(1,x));
const P=(t:number,a:number,b:number)=>clamp01((t-a)/(b-a));
const eOut=(x:number)=>1-Math.pow(1-x,3);
const eIn=(x:number)=>x*x*x;
const backOut=(x:number,s=1.70158)=>1+(s+1)*Math.pow(x-1,3)+s*Math.pow(x-1,2);
const sec=(f:number,at:number)=>(f-at)/30;
const ap=(f:number,at:number,d=0.3)=>eOut(P(sec(f,at),0,d));
const pop=(f:number,at:number)=>Math.max(0,backOut(P(sec(f,at),0,0.35),2.2));
const punch=(f:number,at:number)=>{const t=sec(f,at);if(t<0)return 1;return 1+0.12*eOut(P(t,0,0.2))-0.06*eOut(P(t,0.2,2.5));};
const shake=(f:number,at:number)=>{const t=sec(f,at);return t<0||t>0.4?0:14*Math.exp(-t*10)*Math.sin(t*70);};
Movimentos: tipo cinético (palavra pousa no seu tempo de VO, scale(0.6+0.4*pop)), ±4° assentando em 0.25 s, palavras enfatizadas maiores + âmbar/vermelho), zoom punch em imagens-chave, revelação com máscara circular, transições zoom-through (scale 1→4.2 em ~9 quadros, próxima cena 1.3→1), carimbos rotacionados e chips mono, caixas de destaque vermelhas em capturas de tela, contador de passos, legendas karaokê (palavra atual âmbar + 1.08×), CTA pop com shake, SFX whoosh/pop sob a VO. Cerca de uma batida a cada 1.5–3 s.
Clipes de vídeo: envolva cada <OffthreadVideo> em um <Sequence from={at}> e defina startFrom relativo a ele; caso contrário, o clipe trava em seu último quadro e parece congelado. Faça loop de clipes curtos para batidas longas. Clipes começam no primeiro quadro utilizável.
Transições de áudio: quando uma abertura usa áudio ao vivo (uma música, um clipe) antes da narração, fade para silêncio e deixe ~0.3–0.5 s (uma transição flash/whoosh) antes da primeira palavra do VO para que nunca seja mascarada.
Apresentador opcional (mascote) com sincronia labial
- Identidade de personagem consistente em todos os vídeos. Camadas separadas: corpo (boca fechada pintada), braço em um pivô de ombro sob a borda do casaco, uma capa de ombro estática, sprites de boca
closed/half/open/wide/round. - Conduza a boca a partir do wav do VO, não de um loop:
scripts/build-mouth-track.py→ estados por quadro (fechado em silêncio e hold final, hold mínimo de 2 quadros). Prenda o braço ao alcance do rig; apenas um balanço de imagem inteira não é suficiente. - Monte o apresentador apenas enquanto estiver na tela; capas usam o corpo estático de boca fechada.
5. Render
- Prefira uma máquina GPU se tiver uma (Remotion
--hardware-acceleration, uma config semencodingBufferSize/encodingMaxRate, que quebram o NVENC necessário); recorra a CPU apenas se permitido. Sempre informe qual dispositivo renderizou. - Render cru:
yuv420p+bt709emremotion.config.ts, depois a passagem Reels.
6. Exportação otimizada para Reels (scripts/reels-export.sh, detalhes em docs/REELS_SAFE_EXPORT.md)
1080x1920 SAR 1, H.264 High level 4.1, yuv420p TV range, tags BT.709, CFR 30, GOP 60 fechado, 10 Mbps (mín 8, máx 12), two-pass loudnorm −14 LUFS / −1.5 dBTP, AAC 192k 48 kHz estéreo, +faststart, < 90 s. Também uma prévia pequena < 40 MB (scripts/make-preview.sh).
7. QA (obrigatório, antes da entrega)
- Whisper no MP4 final (
scripts/whisper-check.py): pronúncias erradas, gaguejos, sons estranhos, linhas duplicadas, primeira palavra de cada cena audível. - Folha de contato em cada limite de cena (
scripts/contact-sheet.sh): falhas, sobreposições, texto cortado, zona segura, clipes congelados, abertura/fechamento vazios, marca d'água presente, correspondendo abrand.config.jsone soletrado exatamente. scripts/qa-check.sh: codec/profile/level, pix_fmt, range, tags de cor, CFR, AAC 48k, moov antes de mdat, duração < 90 s, −14 LUFS.- Corrija e re-renderize. Mantenha a versão anterior quando revisar.
8. Sempre entregue junto com o vídeo
- Legendas para IG (gancho, corpo, CTA, hashtags leves), Threads (mais curtas, sem hashtags), TikTok, mais um
.srt. - Quatro capas A–D: 1080x1920 + grade 1080x1350, texto chave dentro do centro 1080x1080; um gancho, uma foto principal, no máximo 2–3 cartões numéricos; folha de contato + deixe o usuário escolher.
- Créditos das fontes e arquivo de verificação de fatos.
- Uma linha em
videos-log.md: título, arquivos, duração, loudness, dispositivo, fontes, status "não postado".
Regras
- Nunca poste, envie DM, faça upload ou compre. Entregue arquivos.
- Sem fatos, estrelas, preços ou resultados inventados. Dê crédito a autores de código aberto na tela.
- Apenas fotos, logotipos e clipes reais; nenhum rosto gerado por IA de pessoas reais. Marque mock-ups como
ilustração. - Use apenas mídia para a qual você tem direitos; avise o usuário quando músicas ou clipes forem protegidos por direitos autorais (risco de muting/reivindicação).
- Sem segredos em arquivos. Faça qualquer pergunta por último, em sua própria mensagem.