Contrato de Ativação
Carregue quando o usuário quiser um vídeo com voz que explique uma funcionalidade ou reproduza um bug, ou quando capturas de tela sozinhas não conseguem mostrar um fluxo (timing, sequência, estado que muda). Para um único estado estático, uma captura de tela é suficiente: não grave.
O CLI está em C:\Users\DESARROLLADORES\Documents\personal\ai-video-evidence (node bin/narrate.mjs). Ele precisa de Node 22+, ffmpeg/ffprobe no PATH, Google Chrome e pip install edge-tts.
Regras Rígidas
- Escreva o roteiro primeiro (
narration.json), valide-o, depois grave. Nunca grave e narre manualmente. - Uma cena = uma ideia e uma ou duas frases. A voz deve descrever o que está na tela naquela cena, nunca o que vem depois.
- O idioma da narração corresponde ao público (Espanhol para PRs do Trip2). Voz padrão
es-CO-SalomeNeural; masculina:es-CO-GonzaloNeural. - Nunca digite senhas. Para aplicativos autenticados, o usuário executa
narrate login <url>e faz login; apontebrowser.storageStatepara o arquivo salvo. Exclua esse arquivo após a gravação e mantenha-o fora do git. - Use apenas dados de teste que o usuário confirmou. Novos registros recebem um prefixo
QA_; nunca edite ou exclua registros existentes. - Mantenha as saídas fora do git (
out/,pr-assets/). - Fluxos não determinísticos (LLM, tarefas assíncronas): verifique o resultado nos quadros gravados. Se o aplicativo fez algo diferente do que a narração diz, grave novamente; nunca entregue um vídeo cuja voz contradiga a tela.
Portões de Decisão
| Situação | Ação |
|---|---|
| Relatório de bug | assets/bug-template.json: contexto → passos → atual (destaque vermelho) → esperado (verde) → evidência → impacto |
| Funcionalidade / Demo de PR | assets/feature-template.json: o que resolve → percurso → casos de borda |
| Espera de backend ou carregamento lento | Coloque em sua própria cena com "speedup": 4; apenas a parte após a narração é acelerada |
Popup nativo <select>, diálogo do SO, ou o aplicativo precisa da sessão ego real do usuário (Trip2 logado) | "recorder": "gdigrab" (apenas Windows). Antes de executar: o usuário faz login no aplicativo no ego, mantém o monitor 1 livre e está pronto para alternar o ego para o espaço de tarefa narrate-<name> quando o executor pedir (o ego mantém as janelas do Agente ocultas; o executor as levanta com Win32, mas o ego só pinta o espaço selecionado). Execução não assistida = use playwright |
Script gdigrab usa call/actionsModule ou waitForResponse | Não suportado (erro de validação): use um backend real ou um servidor local (examples/bug-demo/server.mjs) e waitFor no resultado da UI |
| Execução gdigrab falha com "never became visible on screen" | A janela do espaço de tarefa estava oculta ou coberta. Peça ao usuário para selecionar o espaço no ego e executar novamente; não reivindique ou reutilize o espaço ou as abas do próprio usuário |
| Necessidade de simulação (mocking) ou passos complexos | actionsModule com funções exportadas async (page, ctx), chamadas com { "call": "nome" } |
| Etapa de evidência de um bug | Leia out/<name>/evidence.json (respostas com falha, erros de console) de uma primeira execução e coloque a requisição/status real no callout evidencia |
Etapas de Execução
- Copie o template correspondente para junto do trabalho (Trip2:
pr-assets/<name>.json) e preenchatitle,baseUrl, cenas, seletores. node bin/narrate.mjs validate <file>; corrija cada caminho reportado.- Se o aplicativo precisar de uma sessão: com
playwright, peça ao usuário para executarnode bin/narrate.mjs login <url> --save pr-assets/state.json, então definabrowser.storageState. Comgdigrab, o usuário faz login no aplicativo no ego antecipadamente (caminho Trip2:baseUrl= a URL local do Trip2,recorder: "gdigrab", cenas curtas, semcall). node bin/narrate.mjs run <file>(outts,record,assembleseparadamente;assemblesozinho re-renderiza sem gravar novamente).- Verifique o resultado: extraia quadros no início das cenas (
scenes.json) comffmpeg -ss <t> -frames:v 1e observe-os; confirme o áudio comvolumedetect; leiaevidence.json(vazio com gdigrab). Com gdigrab, confirme que os quadros mostram apenas a página (sem área de trabalho, barra de tarefas ou outra janela sobreposta). - Entregue
<name>.mp4(H.264 + AAC + legendas suaves) e<name>.srt. Para PRs do Trip2 sigatrip2-pr-delivery: artefatos empr-assets/, anexados ao PR, listados na descrição.
Referência de Ações
goto (relativo a baseUrl), click, hover, check (seletor), fill/select {selector, value}, press {key, selector?}, scroll {selector? | y?}, wait (ms), waitFor (seletor ou {selector, state, timeoutMs}), waitForResponse (substring da URL, também aceita uma resposta já vista na cena), overlay {kind: actual|expected|info, title?, text | html, durationMs?}, screenshot (nome), call (exportação de actionsModule). Seletores são localizadores do Playwright (#id, text=Guardar, role=button[name="Guardar"]). Com recorder: "gdigrab" os seletores vão para o ego como estão: CSS puro, text=..., loc=role:button[name='Guardar'], @ref; call e waitForResponse são rejeitados; check, scroll {selector} e waitFor usam page.evaluate/waitForFunction para seletores CSS puros.
Campos da cena: id (slug), say, chapter {title, description?, durationMs?}, actions, speedup. Nível superior: title, baseUrl, recorder (playwright | gdigrab), gdigrab {framerate: 25, drawMouse: true, tab: "new"}, viewport (apenas Playwright), tts {engine: edge|deepgram|sapi, voice, rate, fallback}, browser {channel, headless, locale, storageState}, captions, showActions, gapMs, actionsModule, output.
Contrato de Saída
Retorne: caminho do vídeo e duração, caminho do SRT, engine TTS usada (e qualquer fallback), cenas com seus tempos de início, o que evidence.json capturou, e qualquer coisa que não pôde ser mostrada (popups nativos, passos instáveis).
Referências
assets/bug-template.json,assets/feature-template.json— esqueletos de roteiro.README.mddo repositório — instalação, comandos, como a sincronia funciona.examples/bug-demo/— exemplo completo funcional com um backend simulado (narration.json, Playwright) e a variante gdigrab (narration-ego.json+server.mjs).