Communitygithub.com

mhuot/promo-video-skill

Produção de vídeo promocional totalmente offline (≈60s) com narração: Kokoro TTS + HyperFrames + FFmpeg + governança OpenMontage. Inclui modelos e um vídeo de demonstração que a skill criou sobre si mesma.

O que é promo-video-skill?

Esta skill capacita qualquer agente de IA de codificação (Claude Code, Copilot, Cursor, Codex, entre outros) a produzir vídeos promocionais narrados de aproximadamente 60 segundos, totalmente offline e sem custos de API. Ela combina uma toolchain local robusta: Kokoro TTS para narração (voz 'af_heart' em português, derivando tempos precisos para sincronização), HyperFrames para composição visual determinística via HTML/CSS/GSAP, FFmpeg para síntese de trilha sonora e codificação final, e OpenMontage para governança do pipeline (ordem de etapas, registro de decisões, revisão pós-render). O princípio central é que o roteiro é travado primeiro, e todas as métricas de tempo são derivadas da narração medida, nunca adivinhadas. A skill enfatiza o 'porquê' (público, dor, transformação, prova, um único CTA), não o 'como funciona', que é delegado a uma skill complementar de vídeo explicativo. Inclui scripts Python para TTS com correção de pronúncia de acrônimos, modelos de composição visual, esquema de registro de decisões e um guia de instalação de bootstrap das ferramentas. A abertura de um vídeo de demonstração produzido pela própria skill exemplifica seu uso prático.

Funciona com✓Claude Code✓Codex CLI✓Cursor✓Antigravity✓Windsurf
npx skills add mhuot/promo-video-skill

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Produção de Vídeo Promocional (toolchain local)

Agente-agnóstico: escrito para qualquer agente de IA de codificação que possa ler arquivos e executar comandos de shell — instalado nativamente para Claude Code, GitHub Copilot CLI / Microsoft Scout e Google Antigravity via install.sh; utilizável a partir de Cursor, Codex, Windsurf e outros como um runbook em markdown simples. Toolchain demonstrada pela primeira vez por Idan Shimon (Microsoft, github.com/idanshimon) — seu vídeo conceito de 58 segundos, produzido por um agente de IA usando esta pilha localmente a custo zero, é a base a partir da qual esta skill foi desenvolvida.

Não presuma um local de instalação: defina PROMO_VIDEO_SKILL_DIR como o diretório que contém este SKILL.md. Seu diretório scripts/ contém o script TTS, seu auxiliar de pronúncia de acrônimos e as dependências TTS fixadas; assets/ contém o esqueleto da composição, modelos de componentes espaciais e o esquema de registro de decisões; references/ contém a inicialização da toolchain (install.md) a ser executada uma vez por máquina.

Princípio central: o roteiro é travado primeiro; cada número downstream é DERIVADO do áudio de narração medido, nunca adivinhado.

Promocional, não explicativo: esta skill vende o PORQUÊ — público, dor, transformação, prova, um único CTA. O mecanismo ('como funciona') tem no máximo um momento de destaque, e somente quando o usuário o direciona; solicitações para ensinar como algo funciona pertencem à skill complementar explainer-video.

Perfis das ferramentas

FerramentaLocalizaçãoVersão testadaLicençaFunçãoInvocação
OpenMontage~/OpenMontagecheckout de julho/2026AGPLv3 (apenas as ferramentas; nada é distribuído no vídeo)Governança do pipeline: ordem das etapas, registro de decisões, gates, disciplina de auto-revisão pós-renderLeia seu AGENT_GUIDE.md + pipeline_defs/animation.yaml; você (o agente) é o orquestrador — nenhum daemon é executado
KokoroPyPIKokoro-82M (hexgrad), kokoro==0.9.4Código Apache-2.0; pesos do modelo Apache-2.0TTS de narração, WAV mono 24 kHz por cenaAmbiente virtual Python 3.12; KPipeline(lang_code="a"), voz af_heart, parâmetro speed
HyperFrames~/hyperframes0.7.57, construído a partir do código-fonteApache 2.0Composição HTML/CSS/GSAP → MP4 determinístico via Chrome headlessnode ~/hyperframes/packages/cli/dist/cli.js <cmd>
FFmpeg~/FFmpeg fonte; binário em um diretório de buildgit master (era N-125608)Build GPL (libx264 habilitado)Síntese de música (aevalsrc), codificação, QA com ffprobe, loudness, empacotamento para plataformasColoque o diretório de build no PATH antes dos comandos do hyperframes
bunnpm-global1.3.14—Constrói o monorepo hyperframesnpm i -g bun (brew cask falhou silenciosamente uma vez)
Node.jsnvm24.x (≥22 necessário)—Executa a CLI do hyperframes—
Pythongerenciado por uv3.12—Inferência do KokoroSEMPRE um ambiente virtual (uv venv --python 3.12 .venv); limpo em black + pylint
espeak-ngHomebrew ou aptqualquerGPLFallback G2P do Kokoro (obrigatório)macOS: brew install espeak-ng; Debian/Ubuntu: sudo apt install espeak-ng
gsaparquivo vendido3.x gsap.min.jsLicença padrão GSAPAnimação de timeline dentro da composiçãoCopie para video/assets/ — NUNCA um <script src> de CDN (determinismo offline)

Verificação do ambiente (uma vez por máquina)

export FFMPEG_BUILD_DIR="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}"
export HYPERFRAMES_DIR="${HYPERFRAMES_DIR:-$HOME/hyperframes}"
export PATH="$FFMPEG_BUILD_DIR:$PATH"
node "$HYPERFRAMES_DIR/packages/cli/dist/cli.js" doctor

FFmpeg, FFprobe, Node e Chrome devem todos passar antes da produção (as outras linhas do doctor são componentes opcionais que esta skill não usa). Se algum dos quatro falhar, siga $PROMO_VIDEO_SKILL_DIR/references/install.md — a inicialização completa a ser executada uma vez por máquina: pacotes do sistema (macOS/Linux), clonagem das ferramentas fonte (incluindo o checkout de referência do OpenMontage), construção do FFmpeg a partir do código-fonte com libx264, construção da CLI do HyperFrames e dicas de permissão do agente. Não carregue esse arquivo quando o doctor já passar.

Chrome: a CLI usa automaticamente um chrome-headless-shell em cache em ~/.cache/puppeteer/ (faz o download uma vez se estiver ausente). A primeira execução do TTS também baixa os pacotes Python e os pesos do Kokoro-82M. Após esses downloads únicos, síntese, validação, renderização e empacotamento têm um caminho offline.

Estrutura do projeto (criar por vídeo, repositório git próprio, commits atômicos)

<projeto>/
  .venv/                          # uv venv, python 3.12
  .gitignore                      # .venv/ __pycache__/ video/snapshots/ .DS_Store
  README.md                       # como foi feito + reprodução (escreva POR ÚLTIMO)
  production/
    research/research-brief.md    # fatos com fontes + tabela honesta de concorrentes
    proposal.md                   # conceito, lista de cenas, promessa de entrega, decisão de duração
    script/script.md              # NARRAÇÃO TRAVADA
    scene_plan/scene-plan.md      # recursos visuais por cena + notas de movimento
    checkpoints/decision-log.json # somente anexação; (categoria, assunto) é a chave
    checkpoints/self-review.md    # evidências pós-render
    assets/audio/                 # WAVs do kokoro + durations.json
    renders/                      # versão master + derivadas para plataformas
    youtube/                      # metadata.md + thumbnail.jpg
  tools/tts_generate.py           # copie desta skill, edite SCENE_NARRATIONS
  tools/tts_pronounce.py          # de scripts/, pronúncia de acrônimos (não edite)
  tools/pronunciation.local.json  # opcional, léxico do projeto
  video/
    index.html                    # A composição
    assets/gsap.min.js            # vendido
    assets/audio/                 # cópias dos WAVs (caminhos relativos à composição)

Etapa 1 — Pesquisa (offline-first)

Explore o próprio repositório/README/docs do assunto — buscando resultados e evidências (números, adoção, resultados antes/depois), não arquitetura. Produza research-brief.md com:

  • Bloco de posicionamento (obrigatório — o roteiro não pode ser travado sem ele). Uma frase cada: público (para quem é), dor (o que eles sentem hoje), transformação (o que muda para eles), diferenciador (o único motivo para escolher isto). Esta é a mensagem; cada etapa subsequente a serve.
  • Fatos do produto, cada um verificado em relação à fonte — mantidos apenas se apoiarem um benefício (o teste do 'e daí?': o que o espectador ganha?).
  • Uma tabela de concorrentes (fraqueza → como o assunto a aborda). Regra de honestidade: conceda pontos reais aos concorrentes (um ✓ na coluna deles compra credibilidade para a sua).
  • Uma lista de 'afirmações liberadas para o roteiro'.

Etapa 2 — Proposta + decisões

Escreva proposal.md: reafirme o bloco de posicionamento, conceito de 5–7 cenas, alvo ≈60s, promessa de entrega ('liderado por movimento, não um slideshow'), tabela da toolchain. Registre em decision-log.json — comece a partir do esquema vazio em $PROMO_VIDEO_SKILL_DIR/assets/decision-log.json (campos: category, subject, selected, options_considered, rejected_because, confidence): pipeline_selection, render_runtime_selection (registre Remotion como a alternativa considerada — regra rígida do OpenMontage), composition_mode (atelier para trabalho principal), voice_selection, music_selection, output_profile, approval_gates e cta_selection — exatamente UMA chamada para ação (dar estrela no repositório / instalar / assistir à demonstração / visitar o site); promos morrem ao terminar com uma lista de funcionalidades em vez de um pedido. Se o briefing do usuário fixou uma escolha, marque approved_by: "user brief". Mudou uma decisão depois? ANEXE uma nova entrada com o mesmo (category, subject) — nunca edite a antiga.

Etapa 3 — Roteiro (o ponto de travamento)

~150–155 palavras ≈ 60s na velocidade 1.1 do kokoro af_heart. Arco promocional (venda o porquê): gancho de importância/dor → revelação (nome + a transformação que promete) → benefícios no mundo do espectador → prova (comparação honesta, resultados reais) → aspiração → o único CTA do registro de decisões. Funcionalidades aparecem apenas como evidência de um benefício: toda frase deve passar no teste do 'e daí?' (o que o espectador ganha?) ou ser reescrita. No máximo UM momento de destaque de como funciona, e somente quando o usuário o direciona — ensinar mecanismo é trabalho da skill explainer-video. Voz: segunda pessoa, presente do indicativo, frases curtas e incisivas ('você entrega mais rápido', não 'isso permite entregas mais rápidas'). Escreva acrônimos naturalmente ('OID', 'MCP', 'IA') tanto no roteiro quanto no texto na tela — no momento da síntese, tools/tts_pronounce.py deriva a forma falada (palavra vs letra por letra) a partir de seu léxico, e acrônimos desconhecidos são soletrados letra por letra e relatados. Classifique termos de domínio em um tools/pronunciation.local.json opcional ({"NASA": "word", "ECG": "letters", "NGINX": "engine X"}). Evite ênfase EM CAIXA ALTA: uma palavra em caixa alta é tratada como um acrônimo. Orçamento de palavras por cena ≈ sua parcela de 60s × 2,55 palavras/s.

Etapa 4 — Narração + derivação de tempo (o truque fundamental)

Crie o ambiente Python 3.12 do projeto a partir das dependências diretas fixadas fornecidas, copie o modelo genérico e edite apenas SCENE_NARRATIONS:

uv venv --clear --python 3.12 .venv
uv pip install --python .venv/bin/python \
  -r "$PROMO_VIDEO_SKILL_DIR/scripts/tts-requirements.txt"
mkdir -p tools
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_generate.py" tools/tts_generate.py
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_pronounce.py" tools/tts_pronounce.py
PYTORCH_ENABLE_MPS_FALLBACK=1 .venv/bin/python tools/tts_generate.py
mkdir -p video/assets
curl -fL https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js \
  -o video/assets/gsap.min.js

A primeira síntese baixa os pesos do Kokoro-82M (~330 MB); execuções posteriores usam o cache e podem ser offline. Ela escreve WAVs por cena + durations.json. Se a execução imprimir um AVISO de acrônimo desconhecido, classifique esses tokens em tools/pronunciation.local.json e execute novamente antes de derivar o tempo.

Trate 150–155 palavras na velocidade 1.1 como uma estimativa inicial, não uma calibração. Total >62s? Aumente a velocidade ou corte palavras, depois meça novamente.

Derive a linha do tempo (padding ≈0,3–0,5s entre cenas):

n_start[0] = 0.5                       # lead-in
scene_start[i] = n_start[i] - 0.15..0.4   # visuais aparecem logo antes da locução
n_start[i+1] = n_start[i] + dur[i] + 0.3..0.35
TOTAL = último n_end + 0.6..0.9 cauda (fade para preto)

Esses números vão em TRÊS lugares que devem concordar: data-start/ data-duration da cena, valores de <audio data-start> e as constantes JS const S1..Sn da linha do tempo. Copie os WAVs para video/assets/audio/.

Etapa 5 — Trilha sonora (sem downloads)

Gere um pad sintetizado determinístico com o FFmpeg construído a partir do código-fonte. Defina TOTAL_SECONDS como o total da composição derivado; nenhuma amostra externa ou referência privada é necessária:

TOTAL_SECONDS=60.5
FADE_SECONDS=3.5
FFMPEG_BIN="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}/ffmpeg"
FADE_OUT_START="$(awk -v total="$TOTAL_SECONDS" -v fade="$FADE_SECONDS" \
  'BEGIN { printf "%.3f", total - fade }')"
mkdir -p production/assets/audio
"$FFMPEG_BIN" -hide_banner -y \
  -f lavfi \
  -i "aevalsrc=0.07*(sin(2*PI*110*t)+0.65*sin(2*PI*110.7*t)+0.45*sin(2*PI*164.81*t)+0.30*sin(2*PI*220.9*t)):s=48000:d=${TOTAL_SECONDS}" \
  -af "highpass=f=55,lowpass=f=1200,afade=t=in:st=0:d=2,afade=t=out:st=${FADE_OUT_START}:d=${FADE_SECONDS},pan=stereo|c0=c0|c1=c0" \
  -c:a pcm_s16le production/assets/audio/music-bed.wav

Mantenha-o esparso; mixado em data-volume="0.12..0.16" soa como atmosfera — para energia promocional, fique no topo dessa faixa, nunca acima da narração. Copie o WAV para video/assets/audio/ e use uma faixa de áudio distinta.

Etapa 6 — Criação da composição (contrato HyperFrames)

Comece a partir de $PROMO_VIDEO_SKILL_DIR/assets/composition-skeleton.html (ele incorpora todas as regras abaixo); antes de escrever HTML, leia superficialmente $HYPERFRAMES_DIR/skills/hyperframes-core/SKILL.md. Estrutura: index.html autônomo, raiz <div data-composition-id="X" data-start="0" data-duration="TOTAL" data-width="1920" data-height="1080">, cenas como <section class="clip" data-start data-duration data-track-index="1">, UMA gsap.timeline({paused:true}) registrada sincronamente em window.__timelines["X"], posições do tween = S<i> + local_offset.

Regras que custam tempo real de depuração — obedeça de antemão:

  1. Cada <video>/<audio> precisa de um id explícito e não vazio. No HyperFrames, áudio sem um pode funcionar em uma prévia do navegador, mas renderiza SILENCIOSO (ferramentas de lint reclamam; não ignore).
  2. Nunca coloque um transform: inicial no CSS em um elemento animado por GSAP — use tl.fromTo(el, {y:24, opacity:0}, {y:0, opacity:1, ...}); o GSAP é dono do transform completo. (opacity: 0 sozinho no CSS é aceitável para revelações apenas com .to().)
  3. O preenchimento de fundo vai em um FILHO de sangria total (position:absolute; inset:0), nunca na raiz (o fundo da raiz pode renderizar como preto).
  4. Elementos de mídia são filhos diretos da raiz, data-track-index em faixas de áudio distintas (ex.: 7=VO, 8=música).
  5. Sem repetições infinitas (repeat: -1 proibido — use finito, ex.: piscar de cursor repeat: 9, yoyo: true), sem Date.now/Math.random, sem buscas de rede, sem scripts de CDN.
  6. id único em todos os lugares; anime apenas transforms/opacidade (+ strokeDashoffset para desenhos de linha SVG).
  7. Elementos que aparecem no meio da cena: estado inicial oculto + tween em S<i>+offset. fromTo tem immediateRender para que buscas de estado pré-tween mostrem o estado de origem — é isso que o torna seguro para busca.
  8. Tokens de design em variáveis CSS :root = o tema; troque ground/ink/accent + pilha de tipos para re-estilizar. Use uma fonte que o renderizador fornece (JetBrains Mono) — fontes do sistema são substituídas de qualquer forma (lint info informa o mapeamento).
  9. Mantenha o texto secundário ≥ WCAG AA na cor de fundo — check FALHA na construção por contraste e imprime a cor compatível a ser usada.
  10. Sobreposições/rolagens intencionais: marque com data-layout-allow-overflow/-overlap/-occlusion em vez de deixar descobertas inexplicadas.

Conselho de motivos de cena: mostre o estado RESULTADO — o mundo do espectador melhorado (contraste antes/depois, a dor desaparecida, o resultado na tela). Extraia vislumbres de apoio da UI/domínio real do assunto (paleta de busca falsa, terminal, árvore, tabela) como evidência de um benefício, não um tour de mecanismo. Os modelos de arco narrativo; os motivos não devem. $PROMO_VIDEO_SKILL_DIR/assets/composition-moodboard.pdf contém exemplos de motivos de cena que funcionam; estude-os antes de escrever a composição. Cada motivo deve responder 'como isso ajuda o espectador a sentir a transformação?'.

Habilidades Relacionadas