Pipeline de Vídeos Curtos Remotion com Cortes no Ritmo
Objetivo: Dado um tópico e uma BGM, produzir um vídeo final de 88–90 segundos / 16:9 / sem narração / legendas bilíngues (chinês e inglês) / cada cena cortada no tempo forte de uma frase musical, além de três versões de capa, pacote de publicação e lista de verificação de fatos. Tudo é código: alterar legendas é alterar strings; re-renderizar leva cerca de 35 minutos.
Quando Usar
- "Crie um vídeo de conhecimento no Douyin sobre este tópico / narração de jogo de estratégia"
- "Faça um vídeo com cortes no ritmo usando tal BGM"
- "Transforme este trecho de romance em vídeo" (IP fictício, consulte
references/fact-check.md) - Necessário pacote completo: vídeo final + capa + texto de publicação + verificação de fatos
Quando NÃO Usar
- Para narração com locução (este processo é narrativa sem áudio apenas com legendas; para locução, é preciso primeiro gerar TTS e alinhar)
- Para montagem com imagens reais/AIGC (este processo usa apenas cenas SVG por código)
- Quando for necessário apenas texto e imagens (sem vídeo)
〇. DNA do Estilo (Leia Primeiro; Tudo é de Testes Reais)
| Dimensão | Especificação | Porquê |
|---|---|---|
| Proporção | 1920×1080 / 30fps (versão vertical usa Composition separada) | Conta já configurada para 16:9; dados mostram maior eficiência de conteúdo |
| Duração | 88–90 segundos (≈42 compassos) | Dentro da faixa de teste "60–90s por episódio" |
| Áudio | Sem narração, BGM + efeitos sonoros sintetizados | Exigência de estilo; também evita custo de alinhamento TTS |
| Legendas | Duas linhas (chinês + inglês), chinês ≤22 caracteres, cada frase com duração ≥2,2 segundos | Estilo da conta (recomendação geral do Douyin é monolíngue; esta é uma escolha da conta) |
| Abertura | Primeiro segundo = uma frase de conflito completa + um objeto concreto | A taxa de abandono em 2 segundos é o maior ponto de vazamento |
| Narrativa | Uma pessoa + um problema + uma cadeia causal | Evitar "enciclopédia de conceitos" e "montagem de grupo" |
| Estrutura | Gancho → Título → Regra → Armadilha → Contra-ataque → Reversão → Revelação → Elevação → Fechamento | Ver references/script-template.md |
| Ritmo | Cada cena corta do tempo forte da frase musical; ações-chave na batida | O corte no ritmo vem da estrutura musical, não de alinhamento manual |
| Imagem | Fundo escuro + tons metálicos/madeira/dourado + fonte grande + poucos marcadores | Legível na miniatura do celular |
| Zona Segura | Elementos da cena com y ≤ 850; legendas em y≈870–1000; cabeçalho superior esquerdo y 50–95 | Onde é mais fácil errar nos testes |
| Final | Deve ter uma lista que pode ser capturada de tela (ponto de favoritar) + uma pergunta | Taxa de favoritos é o maior ponto fraco |
| Rigor | IP fictício deve marcar "ilustração é apenas ilustrativa"; fatos divididos em níveis | Ver references/fact-check.md |
一. Fluxo de 8 Etapas (Execute em Ordem, Sem Pular Etapas)
Etapa 1: Definição do Projeto (Tópico + Confirmação)
- Se o usuário não deu um tópico, primeiro forneça 3 candidatos (cada um com: frase de núcleo / gancho do primeiro segundo / por que pode ser visualizado / ponto de favoritar / risco), e deixe o usuário escolher.
- Os candidatos devem ser verificados quanto à existência antes de serem submetidos: IP fictício deve ter nome de capítulo ou verbete pesquisável; conhecimento deve ter fonte verificável.
- Após a escolha, obtenha o material original do tópico (de preferência parágrafos originais; se for apenas compilação de segunda mão, marque o nível da fonte, veja Etapa 8).
Etapa 2: Áudio e Batidas (Determina Todo o Tempo)
# ① Extrair faixa de áudio (aceita mp4/mp3; se não houver ffmpeg no sistema, usa automaticamente o binário do imageio-ffmpeg)
python scripts/extract_audio.py 输入.mp4 work/ # → work/audio.f32 + work/music.mp3
# ② Batidas / Tempos fortes / Seções / Tonalidade
python scripts/analyze_beats.py work/audio.f32 src/beats.json
# ③ Escanear energia, selecionar janela (passo crucial)
python scripts/scan_energy.py src/beats.json work/audio.f32 --seconds 89
- A saída fornece: START_BAR / END_BAR, gráfico de energia por compasso, porcentagem da janela onde o silêncio (corte de energia) está.
- Coloque a reviravolta no primeiro tempo forte após o silêncio – este é o segundo mais valioso do vídeo inteiro.
- A janela não deve cortar a seção de decaimento final (isso deixaria uma cauda morta).
- Se uma música já foi usada em uma série, dê preferência à segunda metade que não foi usada para evitar repetição visual.
Etapa 3: Escrever o Roteiro (src/script.ts)
- Cada cena declara
bars(quantos compassos ocupa), a soma de todos os bars das cenas deve ser igual a END_BAR − START_BAR (caso contrário,placeScenesescalará proporcionalmente e emitirá um aviso). - Legendas escritas em
subs:{zh, en, at},até a batida dentro da cena (pode ser 4,5 para meia batida). Uma frase ocupando 4–5 batidas é confortável. - Efeitos sonoros escritos em
cues:{id, beat, sfx, vol, impact};impact:'big'= flash branco + tremor de tela + dispersão de cor + sidechain musical que cede 40 quadros. - Orçamento de ritmo:
número de frases × 2,5–3 segundos ≈ duração total. 89 segundos ≈ 30 frases.
Etapa 4: Componentes de Cena e Biblioteca Visual (src/*/kit.tsx + src/*/scenes.tsx)
- Escreva todos os componentes primeiro, depois as cenas: um tópico geralmente tem 6–10 componentes (exemplo: caixa de metal/fechadura/chave/triturador/micro-ondas/silhueta humana/estátua/luz/bilhete de loteria/balcão/fichas).
- Todos os componentes são SVG puro, com coordenadas fixas em 1920×1080, reutilizados via
translate/scale. - Componentes de cena só fazem organizar componentes nas batidas:
const bf = (n) => beatFrame(scene, n), entradas sempre usampp(f, bf(n), 8)para progresso de easing. - Lista de verificação em
references/visual-kit.md.
Etapa 5: Configuração do Projeto
Um projeto contém vários episódios: src/<eposódio>/{script.ts,timeline.ts,fx.tsx,kit.tsx,scenes.tsx,Main.tsx},
registre um segundo <Composition> em src/Root.tsx, cada um com seu próprio beats.json e music.mp3.
- O segundo episódio deve ter seu próprio shell de batidas (Shell/ImpactFlash em
fx.tsxdeve usar o cueFrame deste episódio, senão os pontos de impacto ficarão desalinhados). - Áudio usa
<Audio startFrom={OFF}>, o conteúdo geral fica dentro de<Sequence from={-OFF}>, assim os interiores das cenas sempre usam "quadro musical" para temporização. - Detalhes em
references/pipeline.md.
Etapa 6: Auto-Verificação de Quadros Estáticos (Não Renderize sem Verificar)
node <node> node_modules/@remotion/cli/remotion-cli.js still <Comp> out/s1.png --frame=<ponto médio da cena>
Renderize um quadro por cena e verifique visualmente quatro coisas:
- Legendas estão sobrepondo elementos da cena (mais comum)
- Sobreposição de elementos (marcador sobre marcador, marcador sobre gráfico)
- Zona segura (elementos com y ≤ 850)
- Legibilidade do texto na miniatura do celular (chinês ≥24px, título principal ≥120px)
Etapa 7: Renderização e Auto-Verificação do Vídeo Final
node <node> node_modules/@remotion/cli/remotion-cli.js render <Comp> out/<nome>.mp4 --codec=h264 --crf=18 --concurrency=6
python scripts/check_mp4.py out/<nome>.mp4 # duração / número de faixas / resolução / parâmetros de áudio
check_mp4.py não precisa de ffprobe: analisa diretamente os boxes mp4, confirma faixas vide + soun, duração correta, 1920×1080, AAC 48kHz.
Etapa 8: Entrega
python scripts/make_covers.py --src out/<algum quadro estático>.png --crop x0,y0,x1,y1 \
--title 主标题 --kicker 副标 --sub 一句话 --out-prefix out/capa_XXX
Quatro itens de entrega:
- Vídeo final mp4 (copiado para a raiz do espaço de trabalho, nome do arquivo com o tópico)
- Três versões de capa (16:9 / 3:4 / 9:16) – nunca usar quadro automático
- Pacote de publicação (texto principal + comentário fixado + plano de capa + tabela de decisão de 24 horas), modelo em
references/cover-and-publish.md - Lista de verificação de fatos (obrigatório para IP fictício) + Storyboard do roteiro (tabela de timecodes)
二. Regras de Ferro (Todas Baseadas em Testes Reais)
- O primeiro quadro não é abertura, é um gancho: uma frase de conflito completa + um objeto concreto ("O refém está trancado no micro-ondas, a contagem regressiva está correndo").
- Zona segura de legendas: elementos da cena sempre em y ≤ 850, legendas em 870–1000. Verifique isso primeiro na auto-verificação de quadros estáticos.
- Cada linha de legenda ≤22 caracteres, duração ≥2,2 segundos; frase principal em chinês + tradução em inglês em duas linhas.
- Final deve ser capturável como screenshot: uma lista de três passos/três sinais + "sugiro salvar agora"; finais apenas com reflexões não geram favoritos.
- Silêncio = ponto de reviravolta:
scan_energy.pydirá em qual compasso está o silêncio; coloque a reviravolta mais forte logo depois dele. - Grandes impactos são pontuais:
impact:'big'dispara flash branco + tremor de tela + dispersão de cor + cessão musical; 5–8 vezes durante o vídeo é suficiente; mais que isso causa dormência. - Nada de deslizamento uniforme: todas as entradas usam easing (
Easing.out(cubic)), as tags saem com um pouco de deslocamento + escala. - Fontes: não use "subconjunto de fontes cortado de texto antigo" (novo texto pode faltar caracteres) – use diretamente a pilha de fontes do sistema
'Noto Sans SC','Microsoft YaHei'. - public/ é copiado por inteiro: mantenha apenas os efeitos sonoros usados (exemplo: 148 → 16 itens, economiza 60MB a cada renderização).
- O ETA do Remotion é inflado no início: não se assuste com "3 horas restantes"; estável em cerca de ~1,35 FPS, 2700 quadros ≈ 35 minutos.
- Marcação de três níveis para IP fictício: texto original da obra / compilação de leitores / minha dedução – no vídeo, escreva apenas a parte consensual dos dois primeiros níveis, o resto vai para a lista de verificação.
- Não escreva números fixos no vídeo ("quatro animais do zodíaco" → "vários animais do zodíaco"), não escreva números de capítulo fixos ("capítulo 359" → "por volta do capítulo 359").
三. Convenção de Diretórios
<projeto>/
├── public/music.mp3 # BGM deste episódio
├── public/music.f32(+.json) # Para análise de batidas (pode ser deletado)
├── public/sfx/*.wav # Efeitos sonoros sintetizados por tonalidade
├── src/beats.json # Saída do analyze_beats
├── src/script.ts # Tabela completa do texto (para alterar conteúdo, mexa só aqui)
├── src/timeline.ts # Mapeamento cena → batida forte + OFF/TOTAL
├── src/Root.tsx # Registro do Composition
├── src/fx.tsx # Tremor de tela/flash branco/dispersão de cor/legendas bilíngues
├── src/<episódio>/** # Segundo episódio em diante: script/timeline/fx/kit/scenes/Main independentes
├── tools/ # scripts/ desta skill
└── out/ # Quadros estáticos + vídeo final + capas
四. Arquivos de Referência
references/pipeline.md— Configuração de ambiente e comandos completos (incluindo todas as armadilhas desta máquina: sem ffmpeg / scipy / npm)references/script-template.md— Modelo de estrutura de roteiro + tabela de conversão de batidas + timecodes reais dos dois episódios atuaisreferences/visual-kit.md— Especificações de componentes visuais, zona segura, paleta de cores, armadilhas comuns de sobreposiçãoreferences/sfx-and-mix.md— Síntese de efeitos sonoros (por tonalidade), sidechain, loudnessreferences/fact-check.md— Método de verificação de IP fictício e especificações de marcação "Recontagem por leitores" (inclui API do Bilibili disponível)references/cover-and-publish.md— Especificações de três versões de capa + modelo de pacote de publicação + tabela de decisão de 24 horasexamples/十日终焉-dois-episódios.md— Estrutura, dados e registros de decisão de dois casos reais
五. Limitações (Sincero com o Usuário)
- Este processo não gera narração; para locução, é necessário gerar TTS separadamente e realinhar legendas.
- Em ambientes com restrições de rede (muitos domínios bloqueados por DNS), detalhes de regras de IP fictício podem ter apenas fontes de segunda mão – nesse caso, deve-se seguir a lista de verificação da Etapa 8, sem escrever informações não confirmadas.
- Renderização é trabalho computacional intensivo: em um notebook de 4 núcleos, um vídeo de 89 segundos em 1080p leva cerca de 35 minutos; não prometa "vídeo em minutos".
- Direitos autorais: BGM extraída de vídeos do Douyin é adequada apenas para referência pessoal; ao publicar, use a biblioteca de áudio da plataforma ou o cartão de som original.