O que video-narrado faz?
Entrada: um .md. Saída, nesta ordem:
- Vídeo detalhado 16:9 (2 a 4 min) que percorre o MD completo.
- Versões curtas 9:16 (2 ou 3, menos de 60 s): cada uma pega um achado do vídeo detalhado.
- Um
publicacion.mdpor peça (título, descrição, hashtags e texto alternativo).
Tudo com a voz selecionada, legendas e música de fundo própria.
- Motor:
motor/, dentro desta skill (Playwright 1.63.0 + ffmpeg; Python 3 sem dependências).MOTOR= caminho absoluto dessa pasta. - Projeto: uma pasta por vídeo, ex.
videos/AAAA-MM-DD_tema/, com uma subpasta por peça:largo/,short-1-…/,short-2-…/. Cada peça leva seustoryboard.json. - Instalação (uma única vez): ver
README.md.
Voz selecionada
Por padrão, a voz clonada «audio_pmm» do HeyGen:
campo de create_speech | valor |
|---|---|
voiceId | b088805628184836963fa5d2881bb23b |
engine | elevenlabs |
settings | {"model_id": "eleven_v4"} |
language | es |
Se quem pede o vídeo quiser outra voz, buscá-la com mcp__heygen__list_voices e confirmá-la antes de gerar.
Fluxo
1. Ler o MD e propor as peças
Ler o MD completo. Definir o percurso do vídeo detalhado (todos os achados, em ordem) e um achado por versão curta (o mais forte primeiro). Mostrar a lista de peças antes de escrever os storyboards.
2. Storyboards → aprovação
Uma cena por ideia. O vídeo detalhado, de 8 a 16 cenas; uma versão curta, de 4 a 7 cenas, com um gancho (destacado) na primeira. Exemplo completo: motor/ejemplos/storyboard-desalacion-16x9.json.
{"id": "03-sesiones", "tipo": "barras", "kicker": "Sesiones por caso", "titulo": "Dónde se habló más",
"items": [{"etiqueta": "Caleta Chañaral", "valor": 6}], "destacar": 0, "nota": "Fuente…",
"subtitulo": "Chañaral de Aceituno fue el caso con más sesiones.",
"voz": "Chañaral de Aceituno fue el caso con más sesiones."}
Cabeçalho do storyboard: titulo, serie (o que vai junto a «Rizoma ·» em cima), formato ("16:9" para o detalhado, "9:16" para as versões curtas), fuente_md e, se quiser, musica (ver passo 5).
Tipos de cena (todos aceitam kicker, tono: "oscuro" e lluvia: true):
| tipo | campos | para quê |
|---|---|---|
portada | titulo, bajada | abrir o vídeo detalhado |
cifras | titulo, items[{valor, prefijo?, sufijo?, texto, detalle?}] (1 a 3), destacar | números que contam para cima |
barras | titulo, items[{etiqueta, valor, rotulo?}] (até 8), destacar, nota | comparar quantidades |
hito | fecha, etiqueta, titulo, texto, progreso{i, n} | um fato de uma cronologia |
lista | titulo, items[{marca?, texto, alerta?}] (até 6) | argumentos ou passos |
cita | fecha, texto, quien, nota | o que alguém disse |
destacado | texto, bajada | a frase que precisa ser lembrada; o gancho de uma versão curta |
cierre | bajada, url, fuente | marca e fonte |
Regras editoriais:
- Apenas fatos do MD. O que o MD marca como duvidoso fica de fora ou é dito como tal.
vozé o que se lê: números, anos, porcentagens e siglas vão por extenso (texto_voz.pyrejeita dígitos).subtituloé o que se vê, com cifras.textoé o texto na tela dehito,citaedestacado.- Frases curtas, espanhol do Chile neutro, ~2,9 palavras por segundo. Uma versão curta não passa de ~140 palavras de voz.
- O que é tirado de uma transcrição automática é marcado como paráfrase (
nota). - O que é publicado não nomeia clientes nem plataformas internas. O encerramento leva a fonte.
Mostrar cada storyboard como tabela (cena · tipo · o que se vê · o que se narra) e esperar o visto bom: cada narração gasta cota de voz.
3. Voz (uma chamada por peça)
python3 $MOTOR/texto_voz.py <peça>
Passar o texto que imprime (a voz de cada cena unida com <break time="1.2s"/>) para mcp__heygen__create_speech com a voz selecionada. Com o audio_url que retorna:
python3 $MOTOR/bajar_voz.py <peça> "<audio_url>"
Baixa o áudio e o corta por cena buscando as pausas. Se avisar que faltam pausas, reexecutar sobre o áudio já baixado com um limiar menor: python3 $MOTOR/bajar_voz.py <peça> <peça>/voz/narracion.wav --pausa 0.7 (na prática ElevenLabs encurta um pouco alguma pausa). Se mesmo assim falhar, a voz não respeitou um <break>: perguntar antes de regenerar. Nunca reintentar a geração sozinha após um erro.
4. Construir e renderizar
bash $MOTOR/producir.sh <peça> # vídeo completo
bash $MOTOR/producir.sh <peça> --hasta 15 --salida prueba.mp4 # teste curto
Cada cena dura o que dura sua voz. O MP4 fica em <peça>/salida/video.mp4; leva mais ou menos o tempo do vídeo.
5. Música de fundo
Automática: colchão ambiental sintetizado com ffmpeg (sem direitos de terceiros), 14 dB abaixo da voz, com ducking suave e mixagem final a -16 LUFS. No storyboard: "musica": {"bajo_voz_db": 18} a abaixa; {"archivo": "pista.mp3"} usa uma pista própria (apenas de uso livre, com a licença anotada); false a desliga.
6. Versões curtas
Depois de aprovar o vídeo detalhado, montar cada versão curta como peça separada (formato: "9:16"), reutilizando cenas do detalhado: gancho → 2 a 4 cenas de dado → encerramento. Mesmo passo 3 (uma chamada de voz por peça) e passo 4.
7. Revisão e entrega
- Extrair 4 a 8 quadros com ffmpeg e olhá-los: que a legenda não tape um dado, que nenhum texto saia do quadro e que nenhuma cena fique em branco.
- Escrever
publicacion.mdpor peça: título (≤ 60 caracteres), descrição com a fonte, 3 a 5 hashtags, texto alternativo e o que falta verificar antes de publicar. - Copiar os MP4 para
~/Downloadscom nomes claros (Video_<tema>.mp4,Short_<n>_<tema>.mp4). O áudio e os MP4 não vão para git (**/voz/*.wav,**/salida/).
A partir de um HTML animado próprio
Se já existir um HTML com window.seek(t) e cenas com tempos fixos, escreve-se guion.json à mão (html: [a, b] por segmento) e executa-se preparar.py + render.mjs. Para versões curtas feitas à mão: motor/plantillas/motor-vertical.js.
Formato e zonas seguras
- 16:9: 1920×1080, legenda de 34 px em baixo, frases de até 58 caracteres.
- 9:16: 1080×1920, legenda de 54 px a 400 px da borda inferior, frases de até 34 caracteres; conteúdo entre y=400 e y=1380 (em cima e embaixo vão os botões de cada rede).
- Nenhuma legenda termina com «que», «las», «por» e similares.
Erros conhecidos
- Sem rede: as fontes do Google não carregam e a renderização cai para Arial.
- ffmpeg sem libass (Homebrew): por isso as legendas são desenhadas dentro da página.
- Tipo de cena desconhecido: o vídeo sai em branco; revisar
tipo.