Mapa de la ruta
Contenido detallado
🌐 Controlar la app con agent-browser
agent-browser (con Playwright por debajo) abre la app real en un viewport fijo, navega a la URL, encuentra elementos, ejecuta acciones y toma capturas de pantalla — es lo que captura las pantallas reales que usa el video.
Es una skill de navegación que controla un navegador real (con Playwright por debajo) mediante comandos sencillos: open, snapshot, fill, click, screenshot, eval.
Es el motor de captura. Sin él no hay pantallas reales, y las pantallas reales son lo que diferencia esta skill de unos motion graphics genéricos.
agent-browser, Playwright, app objetivo en ejecución (p. ej., localhost:8000), sin clave de API.
Fijas el viewport (agent-browser set viewport 1280 800) y abre la URL (agent-browser open http://localhost:8000/). La sesión permanece activa entre comandos.
El orden importa: viewport ANTES de abrir, para que las bounding boxes salgan en el mismo espacio que las capturas de pantalla.
set viewport, open, sesión persistente, viewport fijo.
agent-browser snapshot -i lista los elementos interactivos y asigna refs (@e1, @e2…) que usas para apuntar a acciones.
Las refs cambian después de navegar o de que cambie el DOM. Vuelve a tomar una instantánea después de cambios importantes y prefiere selectores estables cuando cambie el estado.
snapshot -i, refs @eN, refs volátiles, nueva captura.
fill llena un campo, click haz clic, screenshot guarda la pantalla, eval ejecuta JS. El scroll se hace a mano por ahora (elemento del roadmap en capture.mjs).
Son los bloques de cada paso de la demo. Cada acción cambia el estado de la pantalla y cada estado se convierte en una captura de pantalla.
fill, click, screenshot, eval, scroll manual (roadmap).
Después de cada acción, agent-browser screenshot assets/shots/01-prompt.png graba la pantalla real de ese estado en PNG.
Es la regla de oro «capturar antes, animar después»: el render es determinístico, así que nada de sitios en vivo — solo capturas reales.
1 toma por estado, assets/shots/NN-id.png, capturar antes/animar después.
Mediante eval, tú lees el getBoundingClientRect() del objetivo y guarda {x,y,w,h}. Es el cuadro exacto al que apuntará el cursor en el video.
La bbox real es lo que hace que el cursor caiga en el centro del botón, no "a ojo". Es el detalle que le da un aspecto profesional.
getBoundingClientRect, {x,y,w,h}, target del cursor, eval --json.
El viewport de captura (p. ej., 1280×800) es el espacio de coordenadas de todas las bboxes y capturas de pantalla. Ancho ≤ ~1280 para que quepa en el canvas 16:9.
Viewport inconsistente = el cursor no acierta el objetivo. Si vuelves a capturar, captura todo con el mismo viewport.
viewport fijo, espacio de coordenadas, ≤ ~1280 de ancho, volver a capturar todo.
🗺️ El actions.json
El archivo de entrada de capture.mjs: describe la URL, el viewport y la lista de pasos con sus selectores y narración. Ejecutar node capture.mjs actions.json genera los shots PNG + el steps.json.
Un JSON con url, viewport, window, eyebrow, ctaNarration, ctaCaption y el array steps. Es el guion que ejecuta capture.mjs.
Es la forma automatizada (recomendada) de capturar: un archivo describe toda la demo de principio a fin.
url, viewport, window, steps[], CTA integrada.
"url": "http://localhost:8000/" e "viewport": [1280, 800]. capture.mjs hace set viewport e open exactamente con esos valores.
El viewport definido aquí es el espacio de coordenadas de los bboxes. Si lo cambias aquí, cambia en todo el video.
url, viewport [W,H], espacio de coordenadas, ≤ ~1280.
Cada elemento de steps tiene id, opcional do, target, flags (intro, click, zoom), caption e narration. La captura se ejecuta en orden.
5–8 pasos + CTA ≈ 35–50s. El primero suele ser la pantalla inicial (intro:true) y el último, el resultado (zoom:true).
arco abrir→acciones→resultado→CTA, intro, zoom, 5–8 pasos.
La acción que se ejecutará antes de la captura de pantalla: fill (CSS selector), click, clickText ({tag,text}), setValue (dispara input/change) y wait (ms).
Sin do, el paso solo toma la captura de pantalla del estado actual. Elegir el tipo correcto evita capturar la pantalla equivocada.
fill, click, clickText, setValue, wait.
target es un selector CSS (string) o {tag,text}. capture.mjs lee el bbox de ese elemento — es hacia donde se dirige el cursor en el video.
O do e o target pueden ser elementos diferentes: puedes llenar un campo y apuntar a otro botón.
target, selector CSS, {tag,text}, bbox del target.
Cada paso incluye caption (leyenda en pantalla) y narration (la voz). Los números y las siglas se expanden: "512" → "quinientos doce".
La narración va al steps.json y, desde ahí, Kokoro genera los WAV. El texto fonético produce una voz natural.
caption, narration, expandir números/siglas, 1 frase por paso.
capture.mjs genera assets/shots/NN-id.png e o steps.json (pantallas + bboxes + flags + captions + narración) — todo listo para el composition-template.
El steps.json es el puente entre la captura (T2) y el render (T3). Es el contrato entre las dos mitades del pipeline.
steps.json, shots/*.png, contrato captura→render.
🎯 Coordenadas, selectores y bounding boxes
Qué hace que el cursor caiga exactamente sobre el control: bboxes relativas al viewport, selectores robustos, el apuntado al centro de la caja, la región de zoom y cómo comprobar que se seleccionó el elemento correcto.
Las bboxes son relativas al viewport (la esquina superior izquierda de la ventana). En el video se convierten en canvasX = WIN_L + sx, canvasY = SHOT_T + sy.
Es el mapeo que coloca el cursor sobre el elemento correcto de la captura de pantalla dentro del marco del navegador.
viewport-relative, WIN_L, SHOT_T, mapeo de coordenadas.
Para cada paso con target, capture.mjs lee getBoundingClientRect() y redondea a {x,y,w,h} en steps.json.
Si no se encuentra el objetivo, la bbox queda null y capture avisa: es la señal de que el selector es incorrecto.
getBoundingClientRect, {x,y,w,h}, target nulo = aviso.
Prefiere data-testid, role o texto visible ({tag,text}) en lugar de refs @eN — que se desplazan cuando cambia el DOM.
Después de "Generar", aparece un enlace de descarga y los refs se desplazan. Los selectores estables sobreviven al cambio de estado.
data-testid, role, {tag,text}, evitar @eN en estado mutable.
El cursor es un SVG con el hotspot en la punta (~6,3 dentro de 42px). El tween usa x = alvoX - 6 para que la punta caiga en el centro de la bbox.
Apuntar al centro del cuadro (no al borde) es lo que da la sensación de un clic preciso y profesional.
hotspot en la punta, centro de la bbox, tween de cursor.
La bbox también posiciona el resaltado (anillo ámbar con resplandor) y, en el paso zoom:true, el acercamiento con transformOrigin en el centro del objetivo.
El resaltado y el zoom reutilizan la misma coordenada del cursor: una bbox correcta sirve para los tres efectos.
highlight (.hlbox), zoom:true, transformOrigin en el objetivo.
Si el objetivo está debajo del pliegue, hay que desplazarse hasta él antes de tomar la captura de pantalla y medir la bbox (hoy se hace manualmente; capture.mjs todavía no se desplaza).
Como las bboxes son relativas al viewport, coinciden con la captura de ese scroll, pero solo si el screenshot y la medición se hacen después del mismo scroll.
scrollIntoView, target fuera del pliegue, scroll = roadmap de capture.mjs.
Compara la bbox con el screenshot: el {x,y,w,h} debe caer sobre el control visible. capture.mjs imprime cada bbox en el registro para verificar rápidamente.
Elegir el elemento equivocado solo se nota en el render. Revisarlo en la captura ahorra un ciclo entero de volver a renderizar.
verificar bbox frente a shot, el registro de capture y validar antes de renderizar.
⏳ Páginas largas, inputs de React y múltiples estados
Los casos difíciles de las demos reales: desplazarse por páginas largas, manejar inputs controlados por React/Vue, esperar una condición en vez de un tiempo fijo y capturar flujos asíncronos con múltiples estados. Aquí queda claro lo que ya funciona y lo que está en el roadmap.
En páginas largas, hay que scrollIntoView en la sección antes de capturar. Hoy esto se hace manejando agent-browser manualmente — capture.mjs todavía no lo hace.
Fue exactamente el caso de inemaVOX. Es el elemento n.º 1 del backlog: agregar una acción scroll/scrollTo a capture.mjs.
scrollIntoView, página larga, captura manual por ahora, scroll = roadmap.
Configurar .value vía eval muestra el texto pero no activa el estado del framework — los botones siguen disabled. Usa el fill nativo de Playwright.
O setValue de capture.mjs dispara input+change y ayuda, pero lo ideal (roadmap nº 2) es el fill @ref nativo.
input controlado, no configurar .value, setValue dispara eventos, fill nativo (roadmap).
Hoy el capture usa wait (ms) de margen. Lo ideal es un waitFor de texto/selector — esperar la condición real en vez de confiar en el tiempo.
La generación lenta (flux2-klein tardó ~2,5 min en el POC) necesita un poll de un <img> real antes del screenshot del resultado.
wait ms (hoy), waitFor (roadmap n.º 3), poll por elemento.
Los pipelines largos (analizar → aprobar → doblar → completado) se capturan como subpasos con nombre, con poll de finalización entre ellos.
Probó la skill en inemaVOX: 14 pasos, 2:08. La consulta se hizo con un script manual; incorporarla es el roadmap nº 4.
subpasos con nombre, sondeo de finalización, demo de 14 pasos.
Algunos flujos se detienen en estados de espera (p. ej., waiting_approval) hasta que alguien lo apruebe. La captura debe reconocer ese estado y continuar.
Uno wait de tiempo fijo no lo resuelve: el estado cambia cuando hay aprobación, no cuando el reloj marca la hora. De ahí la necesidad de waitFor.
waiting_approval, estado activado por evento, poll de estado.
Refs que cambian, eval --json anidado (data URL en data.result), captura de pantalla dentro de los límites del canvas, viewport inconsistente.
Son los errores que más tiempo cuestan. Aplicarlos ANTES de renderizar evita volver a renderizar por un detalle tonto.
refs volátiles, data.result, límites del canvas, gotchas.md.
Funciona hoy: actions.json con fill/click/clickText/setValue/wait, bboxes, steps.json. Hoja de ruta: scroll, fill nativo, waitFor, poll multiestado integrado, 9:16, v3.
Conocer el límite evita prometer lo que la skill aún no hace y te indica dónde todavía debes manejar agent-browser manualmente.
v1 actual, backlog, scroll/fill/waitFor/poll, v3 grabación de pantalla.