Communitygithub.com

Demo de pitch deck (app real)

Gera um demo narrado de 1–2 min dirigindo o app real com Playwright, medindo narração e caixas de câmera, e renderizando captions, cards e música no Remotion. Recorte em ~2 min após mudanças de UI. README com demo final.

O que é Demo de pitch deck (app real)?

Launch Video passo 1: gravação Playwright do app real → edição Remotion sincronizada à VO.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add RoderickQiu/pitch-deck-video-skill

Perguntar na sua IA favorita

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

Documentação

/pitch-deck-video

Gere um vídeo de demonstração de produto narrado a partir de um aplicativo web local em execução. A edição é derivada, nunca cronometrada manualmente, então quando o frontend muda, você regrava e o corte acompanha — sem números de quadro para corrigir.

Construído para o caso que realmente acontece: a interface ainda está em movimento enquanto você precisa do vídeo.

Uso

/pitch-deck-video                          # filma o aplicativo no diretório atual
/pitch-deck-video <caminho-para-o-app>     # filma um aplicativo específico
/pitch-deck-video --rebuild                # regrava e recorta um projeto de vídeo existente
/pitch-deck-video --script                 # apenas a narração mudou; reutiliza a última gravação
/pitch-deck-video --render                 # apenas cards/legendas mudaram; renderiza novamente

A estrutura

Quatro arquivos gerados controlam tudo. Apenas o primeiro é escrito por um humano.

arquivocontémescrito por
shots.jsono que é dito, a voz, a música, o tema e o que o navegador fazvocê
src/vo-durations.jsonquanto tempo cada linha realmente levascripts/tts.mjs
capture/marks.jsonquando cada cena começou na gravação e onde olharscripts/record.mjs
src/frames.jsonquantos quadros vieram da gravaçãoscripts/frames.mjs

src/timeline.ts deriva toda a edição a partir desses arquivos. As durações das cenas vêm do áudio da narração medido. A filmagem é esticada para se ajustar a isso. Os movimentos de câmera vêm das caixas delimitadoras dos elementos medidas ao vivo durante a gravação, então um botão movido move o plano, em vez de quebrá-lo.

Fluxo de trabalho

1 · Estrutura inicial

Copie template/ desta skill para <nome-do-app>-video/ ao lado do app, depois execute npm install. O template vem com JSON de semente para que ele faça verificação de tipo e renderize antes da primeira gravação.

Nunca edite arquivos em ~/.claude/skills/pitch-deck-video/template/ para um único projeto — esse é o template compartilhado. Edite a cópia.

2 · Primeiro, verifique se há um login salvo

Se o app tiver autenticação, procure por um estado de armazenamento do Playwright que o repositório já mantém para seus próprios testes e2e (.auth/*.json, storageState, playwright/.auth/). Aponte app.storageState para ele e a gravação começa logada sem mostrar o fluxo de login na câmera. Só crie uma cena de login se não houver tal arquivo — e, nesse caso, use {"type": {"sel": "…", "env": "DEMO_PASSWORD"}} para que a senha nunca seja escrita em shots.json.

3 · Conheça o app antes de escrever uma palavra

Inicie o servidor de desenvolvimento do app e faça captura de tela de cada rota em 1920×1080, depois leia as imagens. Não escreva narração a partir do código-fonte. Você está escrevendo sobre o que um juiz verá, e apenas as capturas de tela lhe dirão isso.

// script único; o Playwright já vem com o template
for (const r of rotas) {
  await p.goto(base + r, { waitUntil: 'networkidle' });
  await p.waitForTimeout(700);
  await p.screenshot({ path: `/tmp/shots/${r}.png` });
  console.log(r, await p.evaluate(() => document.documentElement.scrollHeight));
}

Anote as alturas de rolagem: qualquer coisa acima de 1080 precisa de uma ação scroll ou nunca aparecerá na câmera.

4 · Escreva shots.json

Comece a partir de template/shots.example.json. Consulte references/shots-reference.md para cada campo e ação.

Extraia os theme.colors dos próprios design tokens do app para que os cards e a filmagem pareçam uma peça única. Preencha cards.arch.nodes com a arquitetura real — quais caixas são chamadas de modelo e quais são código determinístico. Esse detalhe é o que separa uma demonstração de um invólucro, e os juízes procuram por isso.

Regras de narração que importam:

  • 12 a 16 cenas, 1:30 a 1:50 no total. Dentro de um limite de 2:00, deixe 10 segundos de margem.
  • Uma ideia por cena. A cena termina quando a ideia acaba.
  • Diga o número. "Seis pessoas pontuaram, Priya vence" é melhor que "seleciona alguém".
  • Nunca narre a interface. Não "aqui clicamos em Aprovar" — diga o que isso significa.
  • Abra com o problema nas palavras do usuário, antes que o nome do produto exista.
  • Feche com uma frase que você quer que fique na tela.

5 · Construir

APP_DIR=/caminho/para/o/app npm run all

Narração → gravação → quadros → renderização. Inicia o servidor de desenvolvimento se nada estiver servindo app.url, lendo o próprio script dev do app para descobrir como aquele framework usa uma porta. Defina app.devCommand se precisar de algo específico. Típica reconstrução completa: ~2 minutos.

shots.json é validado primeiro, então um ID duplicado ou uma ação desconhecida falha em dois segundos, em vez de produzir um vídeo confuso dois minutos depois.

6 · Controle de qualidade visualizando — isso não é opcional

npm run qa          # um quadro por cena, empilhados em folhas de contato
npm run qa 3        # três por cena, quando você quiser verificar uma transição

Depois leia as folhas como imagens. Avançar pelo vídeo é lento e você perderá coisas; uma folha de contato leva segundos e captura exatamente as falhas que importam.

Verifique: capture/marks.json → warnings está vazio (um seletor ausente é um aviso, não uma falha — você ainda obtém um vídeo e uma lista do que quebrou). Depois: cada legenda cai em um quadro que a suporta? Algum quadro em branco ou branco? O texto pequeno é legível ou precisa de um focus?

references/troubleshooting.md tem todas as falhas que este pipeline já encontrou e a correção para cada uma. Leia-o antes de depurar do zero.

Re-corte após mudanças na interface

Este é o ponto de tudo isso.

APP_DIR=/caminho/para/o/app npm run all

A maioria das mudanças não precisa de mais nada — elementos movidos, páginas com novo estilo, novo texto. O que ainda precisa de julgamento:

  • Uma página foi deletada ou renomeada → redirecione ou substitua aquela cena.
  • Uma funcionalidade foi reescrita → a narração para aquela cena agora é uma afirmação sobre algo que não existe mais. Reescreva a linha.
  • Um seletor realmente desapareceu → verifique a lista de avisos e corrija-o lá.

A narração é armazenada em cache por linha, então apenas as linhas editadas são re-sintetizadas.

Voz

A voz é a maior diferença de qualidade no vídeo final, e a alternativa padrão é realmente ruim. Diga isso claramente antes da primeira construção, não depois.

  • tts.provider: "minimax" — bom. Pergunte ao usuário onde está a chave MiniMax dele e aponte tts.envFile para esse arquivo. Os IDs de voz vêm da lista de vozes do sistema MiniMax; a tag de idioma em uma voz é uma dica, não uma restrição (uma voz com tag ucraniana lê inglês bem com languageBoost: "English").
  • tts.provider: "say" — sintetizador embutido do macOS, e geralmente apenas as vozes legadas estão instaladas. É robótico, pronuncia nomes de produtos errado e é óbvio para qualquer um que assistir. Utilizável para verificar o tempo, fraco para qualquer coisa que um juiz ou cliente verá.
  • Uma gravação humana supera ambos. Coloque arquivos <id>.wav em public/vo/ e execute npm run script; as durações são medidas novamente e todo o vídeo se reajusta sem nenhuma outra edição.

Se não houver chave, construa o vídeo de qualquer forma — mas avise o usuário de antemão que a voz é o ponto fraco e que ou uma chave ou dez minutos com um microfone resolvem isso. Não envie silenciosamente uma narração com say como se estivesse pronta.

O MiniMax usa say como fallback por linha se a API estiver inacessível, então uma execução nunca falha completamente.

Nunca copie uma chave de API para dentro do projeto. scripts/tts.mjs lê MINIMAX_API_KEY / MINIMAX_GROUP_ID do ambiente e, caso contrário, os extrai de qualquer arquivo que tts.envFile nomear. Pergunte ao usuário onde a chave dele está e aponte envFile para ela.

Uma gravação humana supera qualquer sintetizador: coloque arquivos <id>.wav em public/vo/ e execute npm run script — ele as mede novamente e reajusta todo o vídeo.

Música

scripts/music.mjs baixa a faixa nomeada em music.url com yt-dlp e corta uma base na duração atual do vídeo. Avise o usuário para verificar a licença da faixa antes de publicar — faixas de biblioteca geralmente são gratuitas com atribuição na descrição e pagas sem ela. O título e a URL são salvos em public/music/SOURCE.txt para que o crédito seja fácil de copiar.

O que não fazer

  • Não ajuste temporizações manualmente. Se uma cena parecer apressada, a narração é longa demais para o plano — corrija shots.json, não a linha do tempo.
  • Não coloque <Screen /> dentro de um <Sequence>. Ele lê tempo absoluto por design; useCurrentFrame() dentro de uma Sequence retorna quadros locais à Sequence. Isso já quebrou o vídeo antes e o sintoma (filmagem sutilmente fora de sincronia com a voz) é difícil de detectar.
  • Não deixe o tempo de configuração aparecer na câmera. Navegação, carregamento de dados e descarte de um banner acontecem dentro da janela de captura da cena e são esticados sob a narração. Coloque {"cut": true} após os passos de configuração; a filmagem então começa a partir daí.
  • Não filme nada que seja fictício. Se um botão retorna "conecte o backend", deixe-o de fora e diga ao usuário qual cena adicionar quando ele estiver conectado.
  • Não envie sem verificar a lista de avisos.
  • Não narre um número que você vê variar entre execuções, e nunca descreva uma tela como cheia quando a versão desta conta está vazia. Um juiz que detecta uma afirmação falsa desconta o resto.

Habilidades Relacionadas