Legendas + sobreposições para reels
Pega um reel 9:16 já cortado (geralmente 2160x3840 a 30fps, por exemplo a saída de talking-head-edit) e adiciona legendas e sobreposições. Tudo é controlado por um único edit.json (páginas de legenda e sobreposições, em quadros) que ambos os renderizadores leem, para que as versões HyperFrames e Remotion correspondam quadro a quadro.
SK=~/.claude/skills/reel-captions-overlays
PY=$($SK/scripts/find_python.sh) # faster-whisper large-v3 + opencv ($REELKIT_PYTHON, o repo .venv, ou python3)
AUDIO_PY=~/.cache/reel-audio/venv/bin/python # estágio de música (scripts/setup_audio.sh cria)
ANA_PY=~/.cache/reel-audio/analysis-venv/bin/python # análise de estilo de referência (scripts/setup_audio.sh --analysis)
Ferramenta padrão: HyperFrames (Apache-2.0, fixado em [email protected]). Remotion (4.0.539) é mantido como uma compilação de paridade. Remotion é gratuito para indivíduos e empresas de até 3 pessoas; uma empresa maior precisa de uma Licença Empresarial paga para uso comercial (remotion.pro/license). HyperFrames não tem essa condição de licença.
Fluxo de trabalho
- Configuração (primeira passagem).
$SK/scripts/new_reel.sh <reel.mp4> <workdir>Isso transcreve com timestamps de palavras (large-v3), detecta caixas de rosto a cada 0,5s (faces_src.json) e cortes de cena (cuts.txt), copiaoverlays.example.jsonpara<workdir>/overlays.json, e então para. - Preencha
overlays.json. Leiawords_raw.jsonprimeiro.corrections: corrija nomes de marca por sequência de token, por exemplo["Ackme"]→"Acme",["re","-motion,"]→"Remotion,",["Acme","Voice."]→"Acme Voice.". Colar pares de marca em um token os mantém em uma página de legenda. Mantenha linhas em língua estrangeira exatamente como falado (por exemplo "Même voix, autre langue.").sansWindows:[início,fim]segundos de cortes de B-roll, tomadas de tela e intervalos de promptDemo. As legendas lá mudam para a sem serifa pesada (mesma faixa de 75%).overlays: veja a especificação de estilo abaixo e o Plano gráfico. Os tempos estão em segundos, obtidos das temporizações das palavras.sponsored: truepara um reel pago ou de marca. Ele ativa a regra de batida de demonstração (Reels patrocinados abaixo) e o aviso de verificação.
- Construa ambos os projetos.
$SK/scripts/new_reel.sh <reel.mp4> <workdir> <workdir>/overlays.json - Veja antes de renderizar.
cd <workdir>/hyperframes && npx [email protected] snapshot --at 2.5,20,30 --no-end(ounpx remotion still Reel x.png --frame=N --scale=0.5emremotion/). - Renderize. Eles precisam de Chrome, então execute-os fora do sandbox Bash (
dangerouslyDisableSandbox). Dentro dele, o Chrome morre em pesquisas de porta Mach.<workdir>/hyperframes/render.sh <out>_captions_hyperframes.mp4renderiza um layout 1080x1920 superamostrado para 2160x3840 com CRF 16 e faststart.<workdir>/remotion/render.sh <out>_captions_remotion.mp4faz o mesmo com--scale=2, CRF 16, AAC 192k e faststart, então executascripts/repair_remotion.py(veja Peculiaridades).
- Verifique.
$PY -I $SK/scripts/verify.py <reel.mp4> <out.mp4> <workdir>/edit.json <workdir>/faces_src.json <workdir>/qc <label>(sai com código 1 e imprime FAIL se quadros, quadros corrompidos, legibilidade, bordas do cartão ou a oferta do CTA falharem; leva cerca de 9 minutos em um reel 4K de 60s)- Verifica se a contagem de quadros e a duração correspondem à fonte.
- Escaneia cada quadro em busca de corrupção (um quadro de vídeo errado ou blocos pretos).
corrupt_framesdeve ser 0. - Verifica 5 páginas de legenda: a faixa deve estar vazia 1 quadro antes do início de uma página e preenchida 2 quadros depois.
- Mede a mudança de pixel da caixa de rosto sob cada sobreposição. Isso deve ser aproximadamente 0, exceto para as tomadas de tela inteira e cartões promptDemo, que cobrem o rosto propositalmente (eles são deixados de fora das verificações de rosto, quadro corrompido e legibilidade).
- Lista
demo_beats(sobreposições promptDemo, ou qualquer sobreposição com"demo": true). Quandoedit.jsontemsponsored: truee há menos de 2, imprime um WARN e adiciona emwarnings(não é uma falha grave; corrija o reel ou explique o motivo no relatório). - Separador ANTES/DEPOIS (v7, aviso). Para cada par de linha promptDemo antes -> depois, relata
before_after: as palavras que ambos os clipes compartilham, a lacuna na edição e o silêncio medido na renderização, e se a edição tem a faixa de comutação e o SFX de comutação (build_editba). Um par que repete palavras sem tudo isso (lacuna >= 400 ms, faixa, SFX) imprime um WARN: uma linha repetida sem separador parece um erro de edição (veja promptDemo). - Oferta do CTA (v7, verificação difícil). Um
ctacom umaofferdeve estar totalmente visível >= 2,5 s, em >= 40px (13+ px em um telefone 360px), e realmente desenhado (mudança de pixel em sua faixa).<label>_offer_mobile.jpgmostra em tamanho de telefone; veja. Um reel patrocinado cujo CTA não temofferrecebe um WARN. - Legibilidade em tamanho de telefone: reduz 8 páginas de legenda para 360px de largura e mede a espessura da haste, altura do texto e
o halo do contorno (luminância do glifo menos o anel ao redor). Mínimos: haste >= 4,0px, altura >= 28px, halo >= 130.
legibility_okdeve ser verdadeiro.<label>_mobile.jpgmostra os recortes; veja. - Escreve uma folha de contato com um still no meio de cada sobreposição, e uma folha de recorte de sincronia. Abra ambos antes de relatar.
- Música + SFX (estágio padrão; pule com
--no-musicouMUSIC=0). Preencha<workdir>/music_plan.json(copiado demusic_plan.example.jsonna primeira passagem; usa a predefinição de estilo padrãosteady-funk-bed; veja Música e design de som abaixo), então$SK/scripts/music_stage.sh <out_hyperframes.mp4> <workdir> <out>_music.mp4Isso mixa a base e SFX sob a fala, multiplexa na imagem com uma cópia do stream de vídeo (sem recodificação) e o áudio ajustado à duração do vídeo, faz a cópia para telefone<out>_music_mobile.mp4(MOBILE_OUT=para colocar em outro lugar) e executamusic_verify.py, incluindo a verificação de estilo contra a predefinição do plano. Deve imprimir PASS. Recusa-se a sobrescrever uma saída existente (FORCE=1para permitir). Também falha qualquer frase cuja fala esteja a menos de 6 dB acima da música sob ela (voice_over_musicno relatório,--min-voice-over-music): o que importa é se cada linha pode ser ouvida bem. A base é um groove constante sem ducking a cerca de 13 dB abaixo da voz, então uma frase silenciosa pode afundar nela mesmo quando a média da seção passa. Corrija uma falha upstream, com nivelamento de fala do talking-head-edit ou ganho por segmento, não puxando toda a base para baixo. Um reel de entrevista típico aprovado mediu 11,2 dB min e 14,1 dB mediana. Abra<workdir>/qc/music_sections.png. A primeira execução cria~/.cache/reel-audio/venv(scripts/setup_audio.sh). - Cópia para telefone (para envio, quando o estágio de música foi pulado):
ffmpeg -i <out.mp4> -vf scale=720:1280:flags=lanczos -c:v libx264 -preset slow -crf 22 -maxrate 2800k -bufsize 5600k -pix_fmt yuv420p -c:a copy -movflags +faststart <out>_mobile.mp4(cerca de 14-19 MB para 60s, abaixo do limite de 25 MB). Copie o áudio masterizado, nunca recodifique: uma segunda codificação AAC a 128k elevou o pico real de um reel de -1,3 para -0,7 dBTP.
Especificação de estilo (do reel de referência)
Todos os tamanhos abaixo estão no espaço de design 1080x1920 (renderizado a 2x). O CSS compartilhado é templates/style.css.
- Legendas (v2: as legendas v1 eram linhas brancas finas, difíceis de ler em um telefone. Mais pesadas, maiores, com contorno é o padrão.)
- Uma palavra por página, ocasionalmente duas: uma palavra funcional curta se junta ao seu vizinho, e pares de marca são colados.
- O texto segue maiúsculas/minúsculas e pontuação como falado ("conteúdo.", "Então"). Nunca coloque em maiúsculas. Sem destaque por palavra: com 1-2 palavras por página, só adiciona ruído.
- Fonte: DM Serif Display (incluída, fixada em
@fontsource/[email protected], OFL) em 136px, branco. Nunca volte para uma serifa fina como Instrument Serif regular para legendas. Instrument Serif permanece para títulos de cartão em papel ou vermelho. - Contorno: uma cópia contornada da palavra (
::beforecomdata-t,-webkit-text-stroke: 6px, então 3px fora do glifo) em quase preto a 86%, pintada atrás do preenchimento para nunca afinar as letras. Sombra: 0 0 3px, 0 5px 12px e 0 14px 34px, todos escuros. - Ajuste:
build_edit.pydefinefspor página a partir detemplates/fonts/caption_metrics.jsonpara que uma página nunca exceda 820px (por exemplo "automatically." a 127px). Regere as métricas comscripts/caption_metrics.pyse a fonte mudar. - Posicionamento: uma faixa centralizada a 75% da altura (y=1440), abaixo das mãos do orador e do microfone e acima da interface do usuário dos 20% inferiores. Cai para queixo + 6% (limitado a 76%) apenas em close-ups. Em uma configuração típica de mesa, as mãos ficam em 55-72%, então uma faixa "sob o queixo" (60%) fica sobre as mãos.
- Animação: um pop de 4 quadros (escala 0,86→1, y 14→0, fade) que começa um quadro antes, para que a palavra esteja visível em seu primeiro quadro.
- As páginas começam exatamente no quadro inicial da palavra e seguram até a próxima página, ou até o fim da palavra + 0,2s se houver uma pausa.
- Legendas de B-roll e tomada de tela: Inter 900 a 120px com tracking -0,03em, mesmo contorno e mesma faixa de 75%.
- Cartão de título (
titleCard, para a frase de gancho)- Uma caixa vermelho-tijolo
#B23A2E, 810px de largura (75%), com seu topo em y=190. - Linha superior: Anton ALL CAPS a 118px. Abaixo, um subtítulo Instrument Serif branco a 62px.
- Sua parte inferior fica a cerca de 23% da altura do quadro. Isso é deliberadamente mais alto que a referência (borda superior 22-28%), porque o rosto começa a cerca de 26%.
- Uma caixa vermelho-tijolo
- CTA (
cta)- Um "Comente" (82px) serifado itálico branco acima de uma caixa vermelha com a palavra-chave Anton (196px, por exemplo "GUIA"). Mesma faixa superior que o cartão de título.
- A caixa aparece em 3 quadros após o chute.
- Linha de oferta (
offer, reels patrocinados, v7): a oferta da marca sob o queixo em um cartão de papel, por exemplo "Use meu link para um teste GRATUITO de 14 dias." Use a redação da própria marca.\ndefine a quebra de linha, e palavras EM MAIÚSCULAS ("GRATUITO") recebem uma caixa branca sobre vermelha. "Comente / PALAVRA" permanece o elemento principal; a oferta é a linha de suporte.build_edit.pyderivaofferF(deofferAt, padrão o início do CTA + 10 quadros),offerY(queixo + 3% de--facessobre a janela do CTA, mantido em 55-60% da altura, acima da tinta da legenda a cerca de 1385px) eofferFs(Inter ajustado a 720px, máximo 46px; avisa abaixo de 40px). O cartão tem 780px de largura (x 150-930, claro da interface do usuário do lado direito) e inclinado -1,5°. - A oferta deve estar totalmente na tela >= 2,5 s. Se o reel terminar muito cedo depois que o orador disser o CTA, segure o
último quadro:
$SK/scripts/hold_end.sh <reel.mp4> <quadros> <reel_hold.mp4>copia o corte, anexa N cópias codificadas de seu último quadro com silêncio digital, e verifica se a fala decodifica amostra-idêntica. Escolha N para que o reel termine um pouco antes de uma batida musical (batida k = k * 60 / bpm comcue_at0), defina oenddo CTA e oendda seção do plano de música para o novo comprimento, e execute build_edit com o novo--frames. A base toca sob o hold e corta com o último quadro (exemplo: 32 quadros, terminando em 68,2 s, um pouco antes da batida 125 de uma base de 110 BPM em 68,207 s; oferta totalmente visível por 3,2 s).
- Tomada de tela (
takeover, para uma menção de ferramenta ou produto, mantida por 1,5-3s)- Um quadro inteiro vermelho profundo
#8E1F17com uma grade sutil mais clara 8x14 vermelha. - Uma pílula de busca arredondada branca (lupa à esquerda; microfone e lente à direita) cuja consulta itálica em negrito digita ao longo de 14 quadros.
- Abaixo, um cartão arredondado branco com o nome da ferramenta (serifada 128px), uma descrição de uma linha, uma forma de onda vermelha e 2-3 chips.
- Nunca finja uma UI de produto real. Use o cartão neutro com texto apenas. A voz continua por baixo.
- Um quadro inteiro vermelho profundo
- Cartão flutuante (
floatCard, para uma estatística, dica ou rótulo; opcionalkicker,width)- Um cartão de papel
#FBF7F1, 470px de largura, com seu topo em y=200, no lado esquerdo ou direito. Rotacionado ±3-4° com uma sombra profunda. - O conteúdo é um kicker opcional + número Anton grande + rótulo serifado + linha em small caps, ou uma variante de bandeira:
flag: "br"(kicker + bandeira CSS + palavra) ouflag: "us-br"(kicker "Mesma voz, idioma diferente" + bandeira EUA → bandeira BR + palavra). - Bandeiras emoji são desenhadas em CSS, então nunca dependem de uma fonte emoji.
- Um cartão de papel
- Lista de etapas (
steps): um cartão de papel no topo (y 150) com um kicker vermelho e linhas numeradas (DM Serif 54px). Cada item tem seu próprio tempoate aparece quando o orador o diz; o número atual é vermelho, linhas anteriores escurecidas. Use quando o orador disser "três etapas", "primeiro... depois". - Divisão antigo vs novo (
split): dois painéis inclinados lado a lado no topo, escuro "Modo antigo" (riscado) e vermelho "Modo novo". O novo painel
...
[truncado para tradução]