Communitygithub.com

learnermaker/project-demo-video-skill

Produza um vídeo de demonstração narrado e legendado em 1080p (3 minutos ou menos) para qualquer projeto de software, submissão de hackathon ou produto, como código, usando Playwright e ffmpeg-static. Grava o aplicativo real, reproduz a saída do terminal real, percorre o código-fonte real, desenha diagramas, adiciona fala (voz nativa do Windows por padrão, ElevenLabs opcional) e insere legendas. Use quando for solicitado a criar, refazer ou reajustar o tempo de um vídeo de demonstração, apresentação ou submissão, ou para provar em vídeo que um projeto funciona.

O que é project-demo-video-skill?

Este skill permite que um agente de IA (como Claude Code, Cursor ou Codex) construa vídeos de demonstração profissionais de 1080p, com narração e legendas, para qualquer projeto de software, hackathon ou produto. O vídeo é gerado inteiramente como código, garantindo que possa ser re-renderizado em minutos após qualquer alteração. A habilidade se concentra em mostrar a realidade do projeto: o app rodando, comandos de terminal reais, código-fonte autêntico e diagramas. Utiliza Playwright para gravação de tela e ffmpeg-static para processamento de áudio e vídeo. O fluxo de trabalho é dividido em fases, desde análise de requisitos e caça a bugs, passando por storyboard, captura de provas reais, geração de narração, até montagem final e controle de qualidade. O skill impõe regras rigorosas de honestidade na tela, respeito a limites de tempo (menos de 3 minutos), sigilo de segredos e uso apenas de recursos gratuitos. O resultado inclui dois arquivos MP4 (um com áudio, outro com legendas), um arquivo SRT de legendas, uma miniatura (thumbnail) e documentação (script, lista de cenas, relatório). Suporta Windows (voz nativa), macOS (say) e Linux (espeak-ng).

Funciona com✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/learnermaker/project-demo-video-skill/tree/HEAD/skills/project-demo-video

Perguntar na sua IA favorita

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

Documentação

project-demo-video

Construa o vídeo de demonstração como código para que possa ser re-renderizado em minutos após qualquer alteração. Tudo na tela é real: o aplicativo em execução, a saída real dos comandos, os arquivos fonte reais. Nada é uma maquete.

Este skill foi escrito para que um agente de codificação menos capaz possa segui-lo passo a passo. Siga as fases em ordem. Cada fase tem uma linha Concluído quando: não prossiga até que seja verdade. Copie os arquivos de templates/ em vez de escrevê-los novamente.

Instalação: copie toda esta pasta (SKILL.md e templates/) para a pasta de skills do agente, por exemplo ~/.claude/skills/project-demo-video/, ou apenas aponte o agente para SKILL.md.

O que você produz

SaídaNotas
<nome>-voiced.mp41920x1080, 30 fps, H.264 + AAC, legendas incorporadas, com voz
<nome>-captions-only.mp4mesma imagem, faixa de áudio silenciosa (o usuário pode escolher esta ou gravar sua própria voz)
<nome>.srtlegendas como arquivo, mesmo texto da narração
thumbnail.png1280x720
narration.md, shotlist.mdroteiro com timestamps reais; cada cena com sua fonte
frames/os quadros de controle de qualidade que você realmente examinou
repo/arquivos do projeto alterados ou novos, espelhados em seus caminhos de repositório
COPY_LIST.md, README-snippet.md, REPORT.mdo que copiar para onde, uma seção README "Veja funcionar", o que está feito e o que é arriscado

0. Regras que você não deve quebrar

  1. Fonte somente leitura. Nunca escreva, faça commit ou envie push nos repositórios reais do usuário. Trabalhe em uma cópia (robocopy/cp, excluindo node_modules, .git, saída de build), depois execute npm ci lá. Mantenha as alterações que valem a pena na pasta de saída, espelhando os caminhos do repositório, mais COPY_LIST.md. Outra ferramenta ou pessoa faz o trabalho com git.
  2. Seja honesto na tela. Qualquer coisa simulada (um dispositivo, um conector, um pagamento, um modelo) é rotulada como simulada no vídeo. Nunca insinue hardware, implantações ou usuários que não existem. Copie a própria tabela de "real vs simulado" do projeto; se o README estiver errado, diga isso no relatório e não repita a afirmação.
  3. Sem segredos na tela ou em arquivos que você enviar: tokens, chaves de API, conteúdo de .env, chaves privadas, e-mails reais. Tokens de desenvolvimento que o projeto documenta (por exemplo Bearer dev-alice) são aceitáveis. Ao mostrar código, escolha intervalos de linhas que excluam segredos.
  4. Nenhuma menção à ferramenta de IA que escreveu o código, ou seu fornecedor, em quadros, narração, legendas ou documentos enviados, a menos que o usuário diga o contrário. Um ID de modelo em tempo de execução que faça parte da configuração do produto pode aparecer como um nome de modelo. Verifique com grep -ri antes de terminar.
  5. Respeite as regras da competição. Leia o limite de duração (geralmente "menos de 3:00"; mire em 2:50) e a regra de tecnologia exigida. O vídeo deve mostrar a tecnologia exigida realmente funcionando, não apenas mencioná-la.
  6. Camada gratuita, sem implantações, sem compras. Não implante, crie recursos em nuvem ou gaste dinheiro. Se uma etapa precisar de uma credencial ou gravação do usuário, pergunte uma vez, claramente, e continue com todo o resto.
  7. Peça ao usuário apenas credenciais, suas próprias gravações, ou uma escolha que seja realmente dele (por exemplo qual voz). Decida todo o resto sozinho e diga o que decidiu.

1. Pré-requisitos (verifique, não presuma)

node --version          # 22+ (24 recomendado; arquivos .mjs devem ser JavaScript puro, sem casts do TypeScript)
  • Na cópia do projeto: @playwright/test (com Chromium instalado) e ffmpeg-static devem existir. Verifique: node -e "import('@playwright/test').then(async m=>{const b=await m.chromium.launch();console.log(b.version());await b.close()})" e node -e "import('ffmpeg-static').then(m=>console.log(m.default))". Se estiver faltando e o projeto proibir novas dependências, coloque-os em uma pasta de ferramentas separada e aponte para ela.
  • Fala: Windows PowerShell com System.Speech (nativo). No macOS use say, no Linux espeak-ng; então você deve adaptar templates/lib/tts.mjs (apenas synthAll e tts.ps1 são específicos do SO).
  • Nenhum ffprobe vem com ffmpeg-static: meça durações a partir dos cabeçalhos WAV (wavSeconds em templates/lib/tts.mjs) e da própria temporização do gravador.
  • Notas sobre shell do Windows: prefira as ferramentas Write e Edit para qualquer arquivo que contenha barras invertidas, regex ou $. A reescrita inline python -c/heredoc de JS corrompe silenciosamente escapes. O sleep em primeiro plano é bloqueado em alguns agentes: aguarde com until grep -q "done" log; do sleep 10; done.

2. Fases

Fase A: Requisitos e mapa de provas

Leia a página de regras, o README, os próprios documentos do projeto e quaisquer notas de história. Escreva uma tabela em suas anotações:

O juiz deve estar convencido de queOnde o vídeo prova issoCena
a tecnologia exigida é chamada no códigochamada real visível: log de requisição, terminal, trecho de código...
a experiência funcionaaplicativo rodando em um navegador...
o que é real vs simuladoa própria tabela do projeto...

Concluído quando toda linha tem uma cena.

Fase B: Espaço de trabalho

  1. Copie o repositório para uma pasta temporária e instale: npm ci.
  2. Copie templates/ para dentro da cópia como video/ (mantenha a estrutura: video/lib, video/pages, video/scenes, video/final.mjs, video/narration.mjs, ...). Adicione ao package.json scripts: "video:final": "node video/final.mjs". Não adicione dependências.
  3. Adicione video/out/ ao .gitignore na cópia.

Fase C: Teste o aplicativo real e caça de bugs (faça isso antes de gravar qualquer coisa)

Inicie o aplicativo da forma que um juiz iniciaria (npm run demo ou o comando do README) em sua porta padrão documentada, para que todo comando mostrado na tela seja literal. Conduza-o com um pequeno script Playwright, tire screenshots em 1920x1080 após cada etapa da história e as examine. Verifique:

  • login, painéis vazios, banners de erro vermelhos, erros no console;
  • se cada estado que a história necessita realmente renderiza (a primeira execução do projeto de referência mostrou um login falho, uma caixa de entrada vazia e uma visão chave ausente, tudo escondido por um rascunho antigo de vídeo);
  • texto duplicado ou cortado.

Corrija bugs reais na cópia, minimamente, execute as próprias verificações do projeto (npm run verify, testes, typecheck) e registre cada correção para COPY_LIST.md. Se o aplicativo não tem como mostrar o tráfego de rede, adicione um pequeno hook opcional (um log de requisição) em vez de falsificar um. Concluído quando toda a história roda limpa duas vezes seguidas e as verificações do projeto passam.

Fase D: Storyboard e narração

  1. Escolha cenas. História de referência (cerca de 2:50):
CenaDuraçãoMostra
gancho12 suma mudança reverbera em vários compromissos (cartão animado)
inicialização6 so único comando que inicia tudo, saída real
sim (o app)60 s8-10 batidas; log de requisição aberto em 2 batidas
terminal de prova17-30 scliente oficial ou CLI contra o mesmo servidor; verificações de autenticação
tour de código16 s3-4 trechos reais que provam a tecnologia exigida
arquitetura, stack cloud, real vs simulado30 sdiagrama, stack fonte, tabela de honestidade, cartão open-source
encerramento12 sslogan, links do repositório, créditos de build, rodapé "X é simulado"
  1. Escreva video/narration.mjs: scenes = [{ id, title, segs: [{ id, text }] }]. Cada seg é uma linha falada e uma legenda (text é mostrado literalmente). Regras: cerca de 2.4 palavras por segundo; total de palavras faladas 330-380; uma ideia por linha; não mais que cerca de 12 palavras em qualquer cartão na tela; letra inicial maiúscula; sem exageros.
  2. Adicione dicas de pronúncia na tabela say apenas para o mecanismo de fala (siglas soletradas, "Alexa+" como "Alexa plus"); nunca altere o texto da legenda. Concluído quando a narração é lida como uma história que um estranho entende e cada linha do mapa de provas é falada ou mostrada.

Fase E: Adapte os templates

Edite apenas o que é específico do projeto:

ArquivoEdição
video/narration.mjssuas cenas e linhas
video/scenes/sim.mjsas etapas do seu app: o que digitar ou clicar, seletores, os zooms da câmera (lens(...), zoomWire)
video/scenes/static.mjscomandos de terminal (CMD), codeBlocks (arquivo + regex da primeira linha + contagem de linhas + regex de destaque), chamadas de página de hook/fechamento
video/proofs.mjs, video/proof-auth.mjsos comandos reais que provam suas afirmações; eles imprimem apenas códigos de status e nomes de erro
video/pages/*.htmltexto, cores, blocos, caixas de diagrama, linhas de tabela, links
video/lib/overlay.mjsseletores SIM_CSS para o layout do seu app (veja regras de Layout), fonte de dados do ticker
video/final.mjsa constante LIMIT e a ordem das cenas (a ordem vem de narration.mjs)
video/thumbnail.mjs, video/docs.mjstítulos e a tabela SHOT

Não edite lib/recorder.mjs, lib/director.mjs, lib/tts.* a menos que algo esteja quebrado.

Fase F: Capture a saída da prova real

node video/proofs.mjs inicia um servidor novo, executa os comandos reais (inspetor oficial ou CLI cliente, verificações de autenticação, saída de instalação/inicialização) e salva o que imprimiram em video/out/proofs.json. As cenas de terminal reproduzem esta saída capturada em um terminal HTML em um tamanho legível. Regras: mostre o texto do comando real (encurte apenas o caminho do pacote); trunque saída muito longa visivelmente (uma linha "... N linhas ..." escurecida) e coloque "Execução gravada" no chip; nunca imprima tokens; formate JSON de forma legível e diga se o fizer.

Fase G: Áudio da narração

Padrão (sem necessidade de conta): node video/final.mjs --rate 2 faz um WAV por linha com a voz nativa do Windows (Microsoft Zira) e mede cada duração. A taxa 1 é cerca de 150 s de fala para o roteiro de referência, taxa 2 cerca de 139 s, taxa 3 é muito rápida. Escolha a taxa mais lenta que mantenha o vídeo inteiro abaixo do limite. Voz opcional com som humano: veja Apêndice A. Tudo abaixo funciona da mesma forma com qualquer uma.

Fase H: Grave e monte

node video/final.mjs --rate 2                   # tudo: tts, provas, gravar todas as cenas, montar ambos os cortes
node video/final.mjs --rate 2 --reuse-proofs    # pular reexecução de provas
node video/final.mjs --scenes sim,close --reuse-tts --reuse-proofs   # regravar apenas algumas cenas
node video/final.mjs --assemble-only            # re-mux (legendas, áudio) sem regravar
node video/final.mjs --tts-dir video/out/tts-human --name my_video --single    # construir a partir de outra pasta de áudio

Uma execução completa leva de 6 a 10 minutos; execute-a em segundo plano e monitore o log. O script falha se o total for 180 s ou mais. Mire em 170 s. Importante: se você alterar o texto da narração ou a voz, as durações mudam, então cada cena deve ser regravada (as marcas vêm das durações). Alterar apenas os visuais de uma cena significa --scenes <id> --reuse-tts.

Fase I: Controle de qualidade (nunca pule, nunca confie no log)

  1. Extraia quadros no final de cada linha de narração do MP4 final: ffmpeg -ss <markEnd-0.3> -i final.mp4 -frames:v 1 frame.png (a linha do tempo está em video/out/timeline.json). Visualize-os. Verifique legibilidade em 1080p, espaço vazio, texto cortado, posição e tamanho da legenda, sincronia (o evento da legenda está na tela), nenhum segredo, nenhuma menção a fornecedor, rótulos de honestidade presentes.
  2. ffmpeg -i final.mp4 -af volumedetect -f null -: média cerca de -22 dB, máxima abaixo de 0 dB.
  3. Duração abaixo do limite em ambos os cortes; ambos os arquivos têm um fluxo de vídeo e um de áudio.
  4. grep -ril "<palavras do fornecedor>" video/pages video/narration.mjs <documentos de saída> não retorna nada, exceto um ID de modelo permitido.
  5. Execute as verificações do projeto novamente (npm run verify; e2e se a UI mudou).
  6. Corrija e re-renderize até que todos passem.

Fase J: Entregáveis

Gere narration.md e shotlist.md com node video/docs.mjs <outdir> (timestamps reais). Copie os MP4s, SRT, miniatura (node video/thumbnail.mjs <png>), os quadros de controle de qualidade e os arquivos do repositório alterados (todos os arquivos diferentes entre o original e sua cópia, em seus caminhos de repositório). Escreva COPY_LIST.md (correções de bugs primeiro, depois novos arquivos, mensagens de commit sugeridas, "execute build e verifique após copiar"), README-snippet.md (comando de execução, arquivo ponto de entrada:linha, arquivo cliente:linha, arquivo skill, link de placeholder do vídeo) e REPORT.md (concluído, o que o usuário deve fazer, riscos). Diga claramente o que você não pôde verificar (por exemplo, você não pôde ouvir a voz).

3. Como o pipeline funciona (leia antes de alterá-lo)

Gravador (lib/recorder.mjs). O recordVideo próprio do Playwright limita a taxa de bits e desfoca texto pequeno, então este usa screencast do Chromium: quadros JPEG (qualidade 92) são carimbados quando chegam, escritos em disco e codificados a 30 fps constantes com libx264 crf 17. Telas estáticas produzem poucos quadros; o último quadro é mantido. Os timestamps vêm de um único relógio (performance.timeOrigin + performance.now()), o mesmo que o diretor usa.

Diretor (lib/director.mjs). Cada linha de narração é um segmento. d.seg(id, actions, {tail}) registra o tempo de início, executa as ações na tela, então espera até que a linha tenha terminado de tocar mais tail * 0.45 segundos (as caudas são aparadas globalmente para caber no limite). As marcas (id, início, fim, texto) são salvas em video/out/<scene>.marks.json. Como o áudio é posteriormente colocado nas marcas registradas, imagem e voz não podem dessincronizar. Regra para uma batida: execute a ação dentro do segmento e certifique-se de que a ação termina antes da narração; se a linha for mais curta que a ação, divida-a em duas linhas (é por isso que uma batida de história se tornou sim9 e sim10).

Áudio (final.mjs). Cada WAV é atrasado para seu início global com adelay, mixado com amix=normalize=0, limitado com alimiter, e preenchido com apad=whole_dur=<total> (sem o preenchimento, -shortest corta o final do vídeo).

Legendas. As pistas são o texto da narração dividido em finais de frase (decimais como "2.0" são protegidos) e em vírgulas quando acima de 82 caracteres, com o tempo dividido proporcionalmente ao comprimento. O .srt é enviado. A versão incorporada usa um arquivo ASS gerado com PlayResX: 1920, PlayResY: 1080 e tamanho de fonte 36. Não incorporar um SRT com force_style: o libass o dimensiona contra uma tela de 288 pixels de altura e o texto fica cerca de quatro vezes maior.

Overlay (lib/overlay.mjs), injetado na página do app gravado apenas (o próprio app não é editado). Manipula:

  • O ticker (barra de status de rolagem com o nome do projeto, timestamp, cabeçalho de "gravação");
  • O selo "real" no canto;
  • O botão de log de requisições (um toggle que mostra uma janela de console overlay);
  • O indicador de beat (um pequeno ponto que muda de cor quando um segmento começa).

Layout. O app é gravado em uma viewport de 1920x1080, mas marginado em 2.5% em cada borda (então a área ativa é cerca de 1824x1026) para deixar espaço para legendas e sobreposições. Use o SIM_CSS em overlay.mjs para ajustar seletores se o app tiver padding ou margens fixas.

Temporização. Porque os segmentos são temporizados pelo diretor e o áudio é colocado nas marcas, a montagem é determinística: a mesma marca de entrada produz a mesma saída. Se uma cena precisar de uma pausa, adicione uma linha de narração vazia ou use d.wait(seconds) dentro de um segmento (mas lembre-se de que isso conta para o limite de tempo).

Manipulação de erros. Se um segmento falhar (um seletor não encontrado, um timeout), o diretor registra o erro, tira um screenshot, e continua com o próximo segmento. O vídeo final tem um card de erro no lugar da cena que falhou. Verifique video/out/errors.log após cada execução.

4. Apêndices

Apêndice A: Vozes humanas (opcional, ElevenLabs)

Para usar uma voz ElevenLabs em vez da voz nativa:

  1. Obtenha uma chave de API em https://elevenlabs.io (não armazene no repositório; use variável de ambiente ELEVENLABS_API_KEY).
  2. Em video/final.mjs, defina const TTS_ENGINE = 'elevenlabs'; e const ELEVENLABS_VOICE = '<voice_id>';.
  3. Execute node video/final.mjs --rate 2 --tts-engine elevenlabs.

Aviso: Isso incorre em custos (o nível gratuito tem um limite de caracteres). O padrão é a voz nativa do SO.

Apêndice B: Solução de problemas comuns

ProblemaCausa provávelSolução
O vídeo está sem áudioFaixa de áudio faltando ou não mixadaVerifique final.mjs; execute ffprobe para confirmar streams de áudio; certifique-se de que amix não está em modo silencioso
Legendas cortadas ou muito grandesArquivo SRT renderizado com force_styleUse o gerador ASS; verifique PlayResX/PlayResY
O app não iniciaDependências faltando ou comando erradoVerifique o comando real no README; teste manualmente antes de gravar
A saída do terminal está vaziaproofs.mjs falhou em capturarExecute node video/proofs.mjs manualmente; verifique se o servidor está rodando

Apêndice C: Referência rápida de comandos

# Renderização completa
node video/final.mjs --rate 2

# Regravar apenas cenas modificadas (economiza tempo)
node video/final.mjs --scenes sim,boot --reuse-tts --reuse-proofs

# Montar novamente sem regravar
node video/final.mjs --assemble-only

# Extrair quadros para QA
ffmpeg -ss 1:23 -i video/out/final.mp4 -frames:v 1 qa_frame.png

Habilidades Relacionadas