Mapa da trilha
Conteúdo detalhado
🌐 Dirigir o app com agent-browser
O agent-browser (Playwright por baixo) abre o app de verdade num viewport fixo, navega a URL, encontra elementos, executa ações e tira screenshots — é o que captura as telas reais que o vídeo usa.
É uma skill de navegação que controla um navegador real (Playwright por baixo) via comandos simples: open, snapshot, fill, click, screenshot, eval.
É o motor da captura. Sem ele não há telas reais — e telas reais são o que diferencia esta skill de um motion graphics genérico.
agent-browser, Playwright, app-alvo no ar (ex.: localhost:8000), sem chave de API.
Você fixa o viewport (agent-browser set viewport 1280 800) e abre a URL (agent-browser open http://localhost:8000/). A sessão fica viva entre comandos.
A ordem importa: viewport ANTES de abrir, para as bounding boxes saírem no mesmo espaço dos screenshots.
set viewport, open, sessão persistente, viewport fixo.
agent-browser snapshot -i lista os elementos interativos e atribui refs (@e1, @e2…) que você usa para mirar ações.
Os refs mudam após navegação ou DOM novo. Re-snapshot após mudanças grandes e prefira seletores estáveis quando o estado muda.
snapshot -i, refs @eN, refs voláteis, re-snapshot.
fill preenche um campo, click clica, screenshot salva a tela, eval roda JS. Scroll, hoje, é feito na mão (item de roadmap no capture.mjs).
São os tijolos de cada passo da demo. Cada ação muda o estado da tela — e cada estado vira um screenshot.
fill, click, screenshot, eval, scroll manual (roadmap).
Após cada ação, agent-browser screenshot assets/shots/01-prompt.png grava a tela real daquele estado em PNG.
É a regra de ouro "capturar antes, animar depois": o render é determinístico, então nada de site ao vivo — só prints reais.
1 shot por estado, assets/shots/NN-id.png, capturar antes/animar depois.
Via eval, você lê o getBoundingClientRect() do alvo e guarda {x,y,w,h}. É a caixa exata que o cursor vai mirar no vídeo.
A bbox real é o que faz o cursor cair no centro do botão, não "no olho". É o detalhe que dá ar profissional.
getBoundingClientRect, {x,y,w,h}, alvo do cursor, eval --json.
O viewport da captura (ex.: 1280×800) é o espaço de coordenadas de todas as bboxes e screenshots. Largura ≤ ~1280 para caber no canvas 16:9.
Viewport inconsistente = cursor erra o alvo. Se recapturar, recapture tudo no mesmo viewport.
viewport fixo, espaço de coordenadas, ≤ ~1280 de largura, recapturar tudo.
🗺️ O actions.json
O arquivo de entrada do capture.mjs: descreve a URL, o viewport e a lista de passos com seus seletores e narração. Rodar node capture.mjs actions.json gera os shots PNG + o steps.json.
Um JSON com url, viewport, window, eyebrow, ctaNarration, ctaCaption e o array steps. É o roteiro que o capture.mjs executa.
É a forma automatizada (recomendada) de capturar: um arquivo descreve toda a demo de ponta a ponta.
url, viewport, window, steps[], CTA embutida.
"url": "http://localhost:8000/" e "viewport": [1280, 800]. O capture.mjs faz set viewport e open exatamente com esses valores.
O viewport definido aqui é o espaço de coordenadas das bboxes. Mude aqui e mudou em todo o vídeo.
url, viewport [W,H], espaço de coordenadas, ≤ ~1280.
Cada item de steps tem id, opcional do, target, flags (intro, click, zoom), caption e narration. O capture executa em ordem.
5–8 passos + CTA ≈ 35–50s. O 1º costuma ser a tela inicial (intro:true) e o último o resultado (zoom:true).
arco abrir→ações→resultado→CTA, intro, zoom, 5–8 passos.
A ação a executar antes do screenshot: fill (CSS selector), click, clickText ({tag,text}), setValue (dispara input/change) e wait (ms).
Sem do, o passo só tira o screenshot do estado atual. Escolher o tipo certo evita capturar a tela errada.
fill, click, clickText, setValue, wait.
target é um CSS selector (string) ou {tag,text}. O capture.mjs lê a bbox desse alvo — é para onde o cursor vai no vídeo.
O do e o target podem ser elementos diferentes: você pode preencher um campo e mirar outro botão.
target, CSS selector, {tag,text}, bbox do alvo.
Cada passo carrega caption (legenda na tela) e narration (a fala). Números e siglas são expandidos: "512" → "quinhentos e doze".
A narração vai para o steps.json e dali o Kokoro gera os WAVs. Texto fonético = voz natural.
caption, narration, expandir números/siglas, 1 frase por passo.
O capture.mjs gera assets/shots/NN-id.png e o steps.json (telas + bboxes + flags + captions + narração) — tudo pronto para o composition-template.
O steps.json é a ponte entre captura (T2) e render (T3). É o contrato entre as duas metades do pipeline.
steps.json, shots/*.png, contrato captura→render.
🎯 Coordenadas, seletores & bounding boxes
O que faz o cursor cair exato no controle: bboxes viewport-relative, seletores robustos, a mira no centro da box, a região de zoom e como conferir que pegou o elemento certo.
As bboxes vêm relativas ao viewport (o canto superior esquerdo da janela). No vídeo viram canvasX = WIN_L + sx, canvasY = SHOT_T + sy.
É o mapeamento que coloca o cursor sobre o elemento certo do screenshot dentro da moldura de navegador.
viewport-relative, WIN_L, SHOT_T, mapeamento de coordenadas.
Para cada passo com target, o capture.mjs lê getBoundingClientRect() e arredonda para {x,y,w,h} no steps.json.
Se o alvo não for encontrado, a bbox vem null e o capture avisa — é o sinal de seletor errado.
getBoundingClientRect, {x,y,w,h}, alvo nulo = aviso.
Prefira data-testid, role ou texto visível ({tag,text}) em vez de refs @eN — que deslocam quando o DOM muda.
Depois de "Gerar", surge um link de download e os refs deslocam. Seletores estáveis sobrevivem à mudança de estado.
data-testid, role, {tag,text}, evitar @eN em estado mutável.
O cursor é um SVG com o hotspot na ponta (~6,3 dentro de 42px). O tween usa x = alvoX - 6 para a ponta cair no centro da bbox.
Mirar pelo centro da box (não pela borda) é o que dá a sensação de clique preciso e profissional.
hotspot na ponta, centro da bbox, tween de cursor.
A bbox também posiciona o destaque (anel âmbar com glow) e, no passo zoom:true, o push-in com transformOrigin no centro do alvo.
Destaque e zoom reaproveitam a mesma coordenada do cursor — uma bbox certa serve para os três efeitos.
highlight (.hlbox), zoom:true, transformOrigin no alvo.
Se o alvo está abaixo da dobra, é preciso rolar até ele antes de tirar o screenshot e medir a bbox (hoje feito na mão; capture.mjs ainda não rola).
Como as bboxes são viewport-relative, elas batem com o shot daquele scroll — mas só se o screenshot e a medição saírem após o mesmo scroll.
scrollIntoView, alvo fora da dobra, scroll = roadmap do capture.mjs.
Compare a bbox com o screenshot: o {x,y,w,h} deve cair sobre o controle visível. O capture.mjs imprime cada bbox no log para conferência rápida.
Pegar o elemento errado só aparece no render. Conferir na captura economiza um ciclo inteiro de re-render.
conferir bbox vs shot, log do capture, validar antes de renderizar.
⏳ Páginas longas, inputs React & multi-estado
Os casos difíceis das demos reais: rolar páginas longas, lidar com inputs controlados por React/Vue, esperar condição em vez de tempo fixo e capturar fluxos assíncronos multi-estado. Aqui fica claro o que já funciona e o que é roadmap.
Em páginas longas, é preciso scrollIntoView na seção antes de capturar. Hoje isso é feito dirigindo o agent-browser na mão — o capture.mjs ainda não rola.
Foi exatamente o caso do inemaVOX. É o item nº 1 do backlog: adicionar ação scroll/scrollTo ao capture.mjs.
scrollIntoView, página longa, captura manual hoje, scroll = roadmap.
Setar .value via eval mostra o texto mas não dispara o estado do framework — os botões continuam disabled. Use o fill nativo do Playwright.
O setValue do capture.mjs dispara input+change e ajuda, mas o ideal (roadmap nº 2) é o fill @ref nativo.
input controlado, não setar .value, setValue dispara eventos, fill nativo (roadmap).
Hoje o capture usa wait (ms) com folga. O ideal é um waitFor de texto/seletor — esperar a condição real em vez de torcer pelo tempo.
Geração demorada (o flux2-klein levou ~2,5 min no POC) precisa de poll por um <img> real antes do screenshot do resultado.
wait ms (hoje), waitFor (roadmap nº 3), poll por elemento.
Pipelines longos (analisar → aprovar → dublar → concluído) são capturados como sub-passos nomeados, com poll de conclusão entre eles.
Provou a skill no inemaVOX: 14 passos, 2:08. O poll foi feito com script à mão; embuti-lo é o roadmap nº 4.
sub-passos nomeados, poll de conclusão, demo de 14 passos.
Alguns fluxos param em estados de espera (ex.: waiting_approval) até alguém aprovar. A captura precisa reconhecer esse estado e seguir.
Um wait de tempo fixo não resolve: o estado muda quando há aprovação, não quando o relógio bate. Daí a necessidade do waitFor.
waiting_approval, estado disparado por evento, poll de status.
Refs que deslocam, eval --json aninhado (data URL em data.result), screenshot dentro dos limites do canvas, viewport inconsistente.
São os erros que mais custam tempo. Aplicá-los ANTES de renderizar evita re-render por causa de detalhe bobo.
refs voláteis, data.result, limites do canvas, gotchas.md.
Funciona hoje: actions.json com fill/click/clickText/setValue/wait, bboxes, steps.json. Roadmap: scroll, fill nativo, waitFor, poll multi-estado embutido, 9:16, v3.
Saber a fronteira evita prometer o que a skill ainda não faz — e indica onde você ainda dirige o agent-browser na mão.
v1 atual, backlog, scroll/fill/waitFor/poll, v3 gravação de tela.