Skill · Vídeo / IA · v1.1.0

Do link do app ao walkthrough narrado.

Você dá a URL. O Claude Code navega o app de verdade, captura as telas reais passo a passo e monta um vídeo com moldura de navegador, cursor animado e narração. Tudo na máquina, sem chave de API.

Capa do projeto video-demonstrativo — vídeo de demonstração de aplicação web
O que é

Uma skill que mostra o app real sendo usado

Não é motion graphics explicando um conceito (isso é a skill video-explicativo): aqui as telas do vídeo são o seu app, capturadas de verdade com navegador automatizado. O resultado é um walkthrough em PT-BR de 35–50s, 16:9, que termina na CTA do INEMA.CLUB.

🖱️ Cursor que acerta o botão

Na captura, a skill pega a bounding box real de cada alvo com getBoundingClientRect. O cursor animado cai no centro do controle — com pulse e ripple no clique. É isso que faz parecer gravação profissional, e não print com seta por cima.

🔒 100% local, sem API key

Captura via agent-browser (Playwright), render HTML→MP4 via HyperFrames, narração PT-BR via TTS Kokoro (voz pf_dora) rodando na própria máquina. Nenhuma chamada paga, nenhum serviço externo.

⏱️ Timing de fonte única

O gerador lê o steps.json e mede a duração de cada WAV com ffprobe. Não existe tabela de tempos na mão: áudio e animação nascem batidos, e os loops de ambiente não deixam cauda muda no fim.

Como funciona

Capturar antes, animar depois

O render do HyperFrames é determinístico — sem rede durante a renderização. Por isso o site nunca é carregado ao vivo dentro do vídeo: primeiro captura-se os screenshots reais, depois anima-se por cima. O viewport fixo da captura vira o espaço de coordenadas onde o cursor mira.

1 · Roteiro (STEPS.md) 2 · Revisão de texto 3 · Captura 4 · Projeto 5 · Narração 6 · Composição 7 · Validar 8 · Render

Roteiro e texto

5–8 passos + CTA (≈35–50s). Cada frase tem duas formas: tela (PT-BR acentuado, botões do app na grafia original — Generate, Upload) e fala (números expandidos e inglês reescrito foneticamente — upload → "âploud"). A revisão vem antes de capturar e narrar.

Captura e coordenadas

O capture.mjs lê um actions.json, dirige o agent-browser pelo app, tira 1 screenshot por estado e grava a bounding box de cada alvo. Saída: assets/shots/*.png + steps.json. Dá pra fazer na mão quando o app é imprevisível (login, estados dinâmicos).

Composição e render

O build-demo.mjs lê o steps.json, mede os WAVs e monta moldura de navegador + cursor global + destaque + zoom no resultado + CTA. Depois: lint, inspect, draft pra conferir frames e render final em high / 30fps.

Pré-requisitos

O que precisa estar na máquina

A skill é auto-contida (já traz as fontes em assets/fonts/) e não depende de nenhum outro projeto. Só precisa do runtime local e do app-alvo no ar.

Node 22+ e FFmpeg

Base do HyperFrames (render HTML→MP4) e do ffprobe, que mede as durações da narração.

node --version   # precisa ser 22+
ffmpeg -version

Chrome do HyperFrames

Navegador headless usado pelo render. Baixa uma vez e fica cacheado.

npx hyperframes browser ensure

TTS Kokoro (PT-BR)

Narração local, voz pf_dora. A primeira execução baixa ~340MB de modelo.

pip install kokoro-onnx soundfile

agent-browser no PATH

Skill de navegação (Playwright) que executa as ações e tira os screenshots reais.

agent-browser set viewport 1280 800

O app-alvo no ar

A URL precisa responder durante a captura — localhost ou público. App com login exige credenciais de teste.

# ex.: seu app servindo em
http://localhost:8000/

A skill instalada

Copie skills/video-demonstrativo/ deste repo para as suas skills do Claude Code.

cp -r skills/video-demonstrativo \
  ~/.claude/skills/
Guia de uso · passo a passo

Do STEPS.md ao MP4

Na prática você pede o vídeo ao Claude Code e ele conduz o fluxo. Abaixo, o que acontece por baixo — os comandos reais, na ordem em que a skill os executa.

1

Escreva o roteiro de passos (STEPS.md)

A lista de ações a demonstrar, com 1 frase de narração por passo. Arco: abrir o app → ação 1 → ação 2 → … → resultado → CTA. O 1º passo é a tela inicial (intro:true); o último de conteúdo é o resultado (zoom:true).

# 5–8 passos + CTA ≈ 35–50s de vídeo
# ex.: escrever prompt → escolher 512² → ajustar altura → Gerar → salvar
2

Revise o texto antes de capturar e narrar

Varra a acentuação PT-BR palavra a palavra. Fixe as duas formas de cada frase: tela (caption + labels, inglês na grafia original) e fala (txt/sN.txt, inglês foneticamente). O Kokoro fonemiza pela grafia escrita — acento errado contamina tela e locução.

# tela:  "2 · Escolha o tamanho — 512²"     (Generate, Upload na grafia original)
# fala:  "Depois, escolha o tamanho. Vamos de quinhentos e doze."
# léxico inglês→PT: upload→âploud · deploy→deplói · Generate→djenereit
3

Capture o app real

Descreva URL, viewport e passos num actions.json; o script abre o app, executa cada ação, tira o screenshot do estado e pega a bounding box real do alvo. Ações: fill, click, clickText, setValue, wait.

node capture.mjs actions.json   # -> assets/shots/*.png + steps.json

# ou na mão, quando o app é imprevisível (login, estado dinâmico):
agent-browser set viewport 1280 800
agent-browser open http://localhost:8000/
agent-browser snapshot -i                 # descobre refs @e1, @e2...
agent-browser fill @e6 "texto"
agent-browser screenshot assets/shots/01-prompt.png
4

Crie o projeto de vídeo

Tudo vive numa pasta única em ~/projetos/output/<nome>/: projeto, captures, áudios, index.html e o MP4 final. Copie as fontes embutidas na skill (ou rode o fetch-fonts.mjs) — sem CDN no render.

cd ~/projetos/output
npx hyperframes init <nome> --example blank --non-interactive

# fontes: copie assets/fonts/ da skill, ou:
node fetch-fonts.mjs
5

Gere a narração com o Kokoro

O template lê o steps.json, escreve assets/txt/sN.txt (1 por passo + CTA, já na forma-fala revisada) e gera os WAVs. Ao final imprime a duração de cada faixa.

bash narration-template.sh   # -> assets/txt/sN.txt + assets/audio/sN.wav

# por baixo, faixa a faixa:
npx hyperframes tts assets/txt/s1.txt --voice pf_dora --speed 0.98 --output assets/audio/s1.wav
6

Componha o vídeo

Copie scripts/composition-template.mjs como build-demo.mjs. Ele lê o steps.json e mede os WAVs com ffprobe — moldura de navegador, cursor global animado, destaque, zoom no resultado e CTA do INEMA.CLUB já vêm prontos.

cp ~/.claude/skills/video-demonstrativo/scripts/composition-template.mjs build-demo.mjs
node build-demo.mjs   # -> index.html (16:9). Não editar à mão.
7

Valide antes de renderizar

Meta: 0 erros no lint e 0 problemas no inspect. Anime o .scene-inner (nunca o wrapper .clip), cenas e captions em tracks alternados, decorativos e moldura com data-layout-ignore.

npx hyperframes lint                  # 0 erros
npx hyperframes inspect --samples 14  # 0 problemas
8

Renderize (draft → high)

Primeiro um draft: extraia 1 frame por passo e mostre ao usuário — você não escuta o áudio, então quem valida a locução é ele. Aprovado, vai pro render final. O MP4 sai na raiz do próprio projeto.

# confere
npx hyperframes render --quality draft
ffmpeg -nostdin -y -ss 12 -i video.mp4 -vframes 1 -update 1 frame.png

# final
npx hyperframes render --quality high --fps 30 --output <nome>-16x9.mp4
Exemplos

Como um passo é descrito

O actions.json é a entrada da captura; o steps.json é o que sai dela e alimenta a composição. Exemplos completos em scripts/actions.example.json e scripts/steps.example.json — o caso de referência é um walkthrough do inemaimg (playground de geração de imagem) gerando uma imagem do zero.

Entrada · actions.json

Você descreve a ação e o alvo do cursor. O script resolve o resto.

{
  "url": "http://localhost:8000/",
  "viewport": [1280, 800],
  "window": { "urlLabel": "localhost:8000" },
  "steps": [{
    "id": "size",
    "do": { "type": "clickText", "tag": "button", "text": "512²" },
    "target": { "tag": "button", "text": "512²" },
    "click": true,
    "caption": "2 · Escolha o tamanho — 512²",
    "narration": "Depois, escolha o tamanho. Vamos de quinhentos e doze."
  }]
}

Saída · steps.json

O alvo virou coordenada real, no espaço do screenshot. É o que o cursor persegue.

{
  "viewport": [1280, 800],
  "steps": [
    { "shot": "00-home.png", "intro": true, "target": null },
    { "shot": "02-size.png", "click": true,
      "target": { "x": 179, "y": 501, "w": 44, "h": 26 } },
    { "shot": "04-result.png", "zoom": true,
      "target": { "x": 668, "y": 128, "w": 484, "h": 324 } }
  ]
}

🎓 Quer o curso completo?

Existe um curso INEMA.CLUB sobre esta skill — 3 trilhas, 10 módulos, do princípio "capturar antes, animar depois" até o render final: inematds.github.io/skill-video-demonstrativo.

Limites conhecidos

O que esta skill não faz (ainda)

Honestidade antes do render: se o seu caso cair aqui, é melhor saber agora.

Tela estática

Estado dinâmico do app (animações, vídeo, dados ao vivo) vira print estático. Movimento real exigiria gravar vídeo da tela — outro caminho, com sincronia de narração mais difícil.

Login

App com autenticação precisa de credenciais de teste. Sem elas, capture só as telas públicas.

Só 16:9

Formato natural, porque telas de app são landscape. 9:16 exigiria recortar e reenquadrar cada shot.

Voz sem atuação

O Kokoro é bom, mas não atua. E você não escuta o resultado — quem valida a locução é sempre o usuário.

Roadmap

De onde veio e pra onde vai

Versionamento v1.yy.xxxyy = recurso, xxx = correção. Histórico completo no CHANGELOG.

1.0.0
Release inicialWalkthrough narrado de app web: captura real com agent-browser + HyperFrames + TTS Kokoro, sem chave de API. Moldura de navegador, cursor global mirando a bounding box real, destaque/zoom e CTA do INEMA.CLUB. Princípio "capturar antes, animar depois". Saída única em ~/projetos/output/<nome>/, sem cauda muda (ambientRepeat).
1.1.0 · atual
Revisão de texto + pronúncia de inglêsNova etapa antes de captura e narração, fechando o buraco do texto que ia direto pra tela e pro TTS sem revisão. Contrato de duas formas por frase (tela vs fala), léxico inglês→PT e a referência revisao-texto.md.
v3 · futuro
Movimento real (gravação de tela)Caminho alternativo já mapeado nos limites: gravar vídeo da tela com agent-browser record em vez de screenshots, pra capturar animações e dados ao vivo. O desafio é a sincronia da narração.