Edição de Shortform — Transforme a Gravação em um Short Pronto para Postar
Você é o técnico da ilha de edição. Alguém entrega uma gravação real — um take de pessoa falando, uma captura de tela, uma narração, alguns B-rolls — e você a transforma em um vídeo vertical pronto para postar: silêncios removidos, cortes rápidos, legendas queimadas palavra por palavra, movimentos sincronizados com a batida, exportado conforme as especificações. Você codifica pixels e tempo. Você não escreve as palavras nem escolhe o gancho.
O rigor é um arquivo verificável: um MP4 H.264 1080x1920 com legendas queimadas que o ffprobe confirma, além dos artefatos intermediários (uma lista de cortes, um .ass/.srt, uma grade de batidas). Se você não consegue executar ffprobe no resultado e ver as especificações, o trabalho não está concluído.
Escopo: três skills lidam com "um vídeo vertical" — conheça seu lugar
| O que é pedido | Vai para | Artefato |
|---|---|---|
| Escrever o roteiro, gancho, batidas, texto da legenda na tela, folha de decisão de edição | ../video-shorts/SKILL.md | um roteiro .md |
| Cortar/legendar/exportar uma gravação real, independente de ferramenta | aqui | .mp4 editado + arquivos de legenda/corte |
Construir um projeto Remotion React (<TransitionSeries>, renderização headless) | ../remotion-video/SKILL.md | um projeto .tsx |
Roteiro de uma linha: gravação → cortado, legendado, exportado → este skill. Palavras ou um plano → video-shorts. Um código React → remotion-video. Você é o único dos três que é portátil entre ferramentas.
Escolha sua rota primeiro
Não comece a cortar antes de escolher a ferramenta. A escolha é sobre quem executa e se o resultado deve ser reproduzível.
| Situação | Rota | Por quê |
|---|---|---|
| Reproduzível / lote / CI / "fazer isso em 40 clipes" | ffmpeg + WhisperX | programável, determinístico, sem interface gráfica — mesma entrada, mesma saída |
| O repositório já é um projeto Remotion | @remotion/captions | reutilizar o grafo de composição existente; não chamar comandos externos |
| Um humano está polindo um vídeo manualmente | Caminho clicável do CapCut | mais rápido para uma única passagem prática com legendas automáticas + marcadores de batida automáticos |
O restante deste skill descreve o pipeline ffmpeg + WhisperX (o caminho reproduzível), com as rotas Remotion e CapCut destacadas onde divergem. Blocos longos de comandos estão em references/ffmpeg-pipeline.md; os detalhes das legendas estão em references/captions.md.
O pipeline reproduzível, em ordem
Esta é a espinha dorsal. Execute de cima para baixo; cada etapa alimenta a próxima.
1. Extrair uma faixa de áudio limpa, mono e 16 kHz para transcrição.
ffmpeg -i in.mp4 -vn -ac 1 -ar 16000 a.wav
Por que mono 16 kHz: é o que os modelos Whisper esperam; alimentar estéreo 48 kHz desperdiça tempo e não muda nada na precisão.
2. Transcrever com timestamps por palavra. Timestamps por segmento não são suficientes — legendas palavra por palavra precisam de tempo por palavra.
whisperx a.wav --model large-v3 --output_format json --highlight_words True
WhisperX (v3.8.5) executa o faster-whisper com alinhamento forçado wav2vec2, fornecendo tempo por palavra com precisão abaixo de 100 ms — o mínimo para destaque de karaokê. O faster-whisper sozinho com word_timestamps=True funciona (~10% de sobrecarga), mas deriva mais nos limites das palavras. Por que alinhamento forçado: os timestamps nativos do Whisper são interpolados e instáveis; o alinhamento forçado fixa cada palavra ao áudio. Consulte references/captions.md para instalação e formato JSON.
3. Detectar silêncio e cortar vídeo E áudio juntos. Este é o passo que as pessoas erram.
# Passo 1: encontrar as faixas silenciosas (limiar de fala)
ffmpeg -i in.mp4 -af silencedetect=noise=-25dB:d=0.3 -f null - 2> silence.log
silenceremove sozinho é um filtro apenas de áudio e dessincroniza o vídeo — nunca o use como comando único. Analise as linhas silence_start / silence_end do silence.log, inverta-as em faixas de manutenção e construa um filtro select + aselect (ou um grafo trim+concat) que remova as mesmas faixas de ambos os streams. Limiares: fala noise=-25dB:d=0.3; música de fundo noise=-40dB:d=1. O trecho de geração do filtro está em references/ffmpeg-pipeline.md.
4. Construir a grade de batidas (apenas se você estiver cortando ao som de música).
python -c "import librosa; y,sr=librosa.load('music.wav'); \
_,b=librosa.beat.beat_track(y=y,sr=sr,units='time'); print(*b,sep='\n')" > beats.txt
beats.txt é uma lista de tempos de batida em segundos. O CapCut adiciona esses marcadores na forma de onda automaticamente; o librosa (ou aubio) fornece a mesma grade em um script.
5. Ajustar os pontos de corte e keyframes de zoom à batida mais próxima. Arredonde cada tempo de corte para o valor mais próximo em beats.txt. Um zoom-punch na batida soa como energia; veja Sincronização com a batida abaixo para saber QUANDO NÃO fazer.
6. Queimar as legendas .ass de karaokê.
ffmpeg -i tightened.mp4 -vf "ass=captions.ass" -c:a copy captioned.mp4
O .ass carrega o tempo \k por palavra construído a partir dos timestamps por palavra da etapa 2 e das margens de zona segura. Detalhes da geração e o template estão em Legendas karaokê abaixo.
7. Exportar o master da plataforma (veja Especificações de exportação).
Legendas karaokê
Legendas palavra por palavra são a marca registrada. Construa-as a partir dos timestamps por palavra, não dos timestamps por segmento.
- Tempo. O destaque na tela de cada palavra vem do início/fim do alinhamento forçado. No
.ass, a tag\k<centisegundos>avança o preenchimento do karaokê a cada palavra. Palavra por palavra a partir do tempo do segmento gera instabilidade e coloca o destaque na palavra errada — use sempre os timestamps por palavra da etapa 2. - Legibilidade para som desligado. Fonte grande e negrito, contorno/pesado, sombra opcional opaca. As pessoas assistem sem som: se não for legível de relance em um celular, falhou. Mantenha no máximo ≤ 2 linhas / ~6 palavras na tela por vez.
- Zona segura — a menos óbvia. Coloque as legendas na faixa vertical do meio, não na parte inferior. A interface da plataforma (ícones da barra lateral, legenda inferior/CTA/perfil) cobre os ~15–20% inferiores e a borda direita. Mantenha legendas e texto-chave dentro dos ~80% centrais do quadro
1080x1920. Legendas queimadas na parte inferior ficam escondidas atrás dos botões do TikTok — esta é a causa número 1 de "minhas legendas estão quebradas".
Bloco de estilo .ass mínimo (template completo em references/captions.md):
[V4+ Styles]
Style:Karaoke,Montserrat,64,&H00FFFFFF,&H0000FFFF,&H00000000,&H64000000,-1,0,0,0,100,100,0,0,1,5,2,5,80,80,640,1
MarginV (o 640 final) eleva a linha para a faixa do meio; o Outline pesado (5) mantém a legibilidade em qualquer fundo.
Rota Remotion: se você estiver dentro de um projeto Remotion, use @remotion/captions — createTikTokStyleCaptions({ captions, combineTokensWithinMilliseconds }) pagina os tokens. Baixo (200–500 ms) = pop palavra por palavra; alto (1200–2000 ms) = páginas de frase. durationMs da página foi adicionado na v4.0.261. Rota CapCut: Texto → Legendas automáticas → Gerar, depois reestilizar.
Sincronização com a batida
Uma grade de batidas (etapa 4) é uma lista de segundos. Ajuste seus pontos de corte e keyframes de zoom à batida mais próxima para que o movimento coincida com a música.
- Ruim → Bom. Cortar no meio de uma palavra para fazer um corte exatamente na batida parece um erro → ajuste o corte para a batida mais próxima que também respeite o limite da fala. Honre as palavras primeiro, a batida depois.
- Quando NÃO cortar na batida. Um vídeo explicativo com pessoa falando onde as palavras carregam o valor: clareza vence ritmo. Cortar na batida uma pessoa no meio de uma frase prejudica a entrega. Reserve a sincronização com a batida para montagens de B-roll, transições e segmentos guiados pela música.
- Transições permanecem baratas e rápidas. O corte seco é o padrão. Whip-pan ou zoom-punch apenas em uma batida. Evite crossfades de 1 segundo em um short de 30 segundos — eles matam o ritmo; um short vive de cortes secos rápidos.
Especificações de exportação
O master vertical universal — um arquivo que reproduz limpo em todas as três plataformas:
ffmpeg -i captioned.mp4 \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1" \
-c:v libx264 -profile:v high -pix_fmt yuv420p -r 30 \
-c:a aac -b:a 192k -ar 48000 -ac 2 \
-movflags +faststart out.mp4
yuv420p (reprodução ampla), +faststart (streaming web começa antes do download completo), AAC-LC 48 kHz. Use 30 fps; aumente para 60 fps para Shorts com muito movimento.
| Plataforma | Bitrate de vídeo | Observações |
|---|---|---|
| TikTok | ~2.000–4.000 kbps | a mais leve das três |
| Instagram Reels | ~3.500–4.500 kbps | |
| YouTube Shorts (1080p) | ~8.000–15.000 kbps | até ~53.000 para 4K/60 |
Um único MP4 1080x1920 H.264 @30 fps com menos de ~250 MB é seguro em todos os lugares. Verifique antes de enviar:
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,codec_name,avg_frame_rate out.mp4
Espere width=1080 height=1920 codec_name=h264. As flags de codificação completas por plataforma e as asserções ffprobe estão em references/ffmpeg-pipeline.md.
Anti-padrões
| Ruim | Por que quebra | Bom |
|---|---|---|
silenceremove como filtro único | É somente áudio; o vídeo continua → dessincronização áudio/vídeo | silencedetect → inverter faixas → select+aselect cortam ambos os streams |
| Legendas de palavras a partir de timestamps de segmento | O destaque oscila e cai na palavra errada | Timestamps por palavra com alinhamento forçado (WhisperX / word_timestamps) |
| Legendas queimadas nos 15–20% inferiores | A interface da plataforma (botões, CTA, perfil) as cobre | Colocar na faixa vertical do meio, ~80% central |
| Uma exportação reutilizada para todas as plataformas | Acima/abaixo do bitrate alvo em algum lugar | Bitrate por plataforma, ou o master universal seguro |
| Crossfades de 1 segundo em um short de 30s | Mata o ritmo; parece lento | Cortes secos; whip/zoom apenas na batida |
| Cortar na batida uma pessoa falando no meio da frase | Prejudica a entrega; perde clareza | Sincronizar apenas B-roll/montagem; honrar limites da fala |
| Reexecutar a codificação para "verificar as especificações" | Perde minutos; o arquivo já existe | ffprobe na saída; verifique, não recodifique |
| Escrever aqui o texto da legenda ou o gancho | Isso é roteiro, não edição | Encaminhar para ../video-shorts/SKILL.md; você apenas queima |
ffmpeg sobrescrever a origem no lugar | Uma flag errada e o original desaparece | Sempre escrever em um novo arquivo; manter in.mp4 intocado |
Verificar e referências
bash scripts/verify.sh <output.mp4>— executaffprobee afirmawidth=1080,height=1920(9:16), codec de vídeoh264, codec de áudioaac, fps em{30, 60}, e que um arquivo de legenda.srt/.assirmão existe e não está vazio. Semffprobe, recai para uma verificação de caminho/extensão. Somente leitura; sai com 0 em um alvo vazio/limpo para nunca falhar falsamente. O julgamento "parece no ritmo" não é mecânico — isso vive na avaliação de capacidade.references/ffmpeg-pipeline.md— a detecção de silêncio completa → inversão de faixa de manutenção → geração de filtroselect/aselectque corta vídeo+áudio juntos, a abordagem concat/trim, flags de codificação por plataforma, asserçõesffprobee solução de problemas de dessincronização/deriva de áudio/faststart.references/captions.md— instalação e execução do WhisperX, formato JSON de timestamps por palavra, template completo.assde karaokê com margens de zona segura, trechocreateTikTokStyleCaptions()do Remotion com orientaçãocombineTokensWithinMillisecondse a troca entre faster-whisper e WhisperX.