PTENES
MÓDULO 1.2

🧠 Capturar primero, animar después

El principio que rige toda la skill. Cómo el render de HyperFrames es determinístico (sin red), nunca se carga el sitio en vivo en el video: se captura la pantalla real antes y se anima por encima. El viewport fijo de la captura se convierte en el espacio de coordenadas del cursor.

6
Temas
~30
Minutos
Básico
Nivel
Concepto
Tipo
CAPTURAR → MEDIR → ANIMAR ① CAPTURA captura de pantalla real viewport 1280×800 ② CUADRO DELIMITADOR x,y,w,h getBounding... viewport-relative ③ CURSOR objetivo apunta al recuadro · haz clic ⚙️ Render determinista — sin red durante el render el mismo viewport y scroll garantizan la consistencia entre shot ↔ coordenada
1

⚙️ Render determinista

HyperFrames renderiza el HTML en frames de forma determinista: con el mismo HTML y la misma timeline, el video sale idéntico. Para eso, no hay acceso a la red durante el renderizado.

Concepto principal

Determinístico significa que el render no depende de nada que pueda variar: no hace fetch, no carga imágenes remotas ni consulta APIs durante el proceso. Cada frame es una función pura del HTML + tiempo.

Es exactamente lo que garantiza que el video se pueda reproducir y que la animación coincida con el audio frame a frame.

⚠️
La red durante el render = inconsistencia

Si un frame dependiera de una solicitud, el resultado cambiaría según la latencia, el estado del servidor o los datos del momento. El render perdería previsibilidad y se rompería la sincronía con la narración.

Conceptos clave
🔁
Reproducible
Mismo resultado
🚫
Sin red
Ningún fetch
🎞️
Cuadro por cuadro
Tiempo controlado
🔗
Audio sincronizado
Sincronía exacta
2

🚫 Nunca el sitio en vivo

Como consecuencia directa del renderizado determinista, la app nunca se carga en vivo dentro del video. Nada de un iframe que apunte a la URL real durante el renderizado.

✓ La forma correcta
  • ✓ Capturas de pantalla reales guardadas en assets/shots/
  • ✓ Imágenes locales referenciadas en el HTML del video
  • ✓ Todo integrado antes de que comience el render
  • ✓ Animación sobre la imagen estática
✗ Qué no hacer
  • ✗ <iframe src="https://app…"> en el video
  • ✗ Cargar imágenes mediante una URL remota durante el renderizado
  • ✗ Esperar a que la app responda durante el renderizado
  • ✗ Depender de fuentes mediante CDN (usa las locales)
💡
El marco disimula que es una captura

El screenshot estático se coloca dentro de un marco de navegador (barra + URL) y se le superponen un cursor y zoom. Para quien lo ve, parece una grabación de pantalla en vivo, pero es una imagen más animación.

3

📸 Se capturan screenshots reales ANTES

La etapa que marca toda la diferencia ocurre antes del render: se navega por la app real con agent-browser y se toma una captura de pantalla por cada estado del recorrido.

El orden del pipeline
1
Abrir la app en un viewport fijo

agent-browser set viewport 1280 800 y abrir la URL. El viewport se define una vez y se mantiene.

2
Ejecutar la acción del paso

Completar un campo, hacer clic en un botón, esperar un resultado: la acción que demuestra ese paso.

3
Tomar 1 screenshot por estado

Cada estado se convierte en un assets/shots/NN-id.png — la base visual de ese paso.

4
Obtener el bounding box del objetivo

Junto con el shot, se mide el cuadro real del elemento al que apuntará el cursor. Todo eso se convierte en steps.json.

💡
Dos formas de capturar

Automatizado (capture.mjs + actions.json) para apps predecibles, o control manual del agent-browser paso a paso cuando hay inicio de sesión o estados dinámicos. Los detalles están en la Ruta 2: Captura.

4

🖼️ El viewport fijo se convierte en el espacio de coordenadas

Este es el concepto más importante del módulo: el viewport usado en la captura define el sistema de coordenadas en el que se posiciona todo después. Por eso es sagrado.

Concepto principal

Si la captura se hizo en un viewport de 1280×800, entonces la captura de pantalla mide 1280×800 y cualquier coordenada (x, y) se refiere a ese espacio. El cursor, el zoom y el marco trabajan todos en ese mismo sistema.

La regla del viewport fijo
# el MISMO viewport para la captura y el recuadro
viewport = 1280 × 800 # definido una vez
captura de pantalla → 1280 × 800 px # mismo tamaño
box.x, box.y → relativos a 1280 × 800

# ancho ≤ ~1280 para que quepa en 16:9
⚠️
Cambiar el viewport rompe la alineación

Si la captura de pantalla sale de un viewport y la bounding box de otro, las coordenadas no coinciden: el cursor cae en el lugar equivocado. Por eso el viewport debe ser idéntico en toda la captura.

5

📦 Bounding boxes relativas al viewport

La posición de cada elemento objetivo no se estima «a ojo»: viene de getBoundingClientRect, que devuelve coordenadas reales relativas al viewport.

Medir el cuadro real del objetivo
# eval en agent-browser obtiene el recuadro del elemento
const r = el.getBoundingClientRect();
return {
x: Math.round(r.x),
y: Math.round(r.y),
w: Math.round(r.width),
h: Math.round(r.height)
}; # coordenadas en el espacio de la captura de pantalla
✓ Por qué importa el cuadro real
  • ✓ El cursor llega al centro exacto del control
  • ✓ Funciona incluso si el diseño es responsivo
  • ✓ El resaltado/zoom encuadra el elemento correcto
  • ✓ Es lo que le da un aspecto profesional al video
✗ Calcular «a ojo» falla
  • ✗ Las coordenadas estimadas no aciertan en el control
  • ✗ Se rompen con cualquier cambio de diseño
  • ✗ No siguen el desplazamiento ni el tamaño del elemento
  • ✗ Dan ese aspecto amateur de "casi listo"
6

🖱️ El cursor apunta a las cajas — consistencia entre shot↔coordenada

Con los screenshots y las cajas listos, el cursor se anima en la timeline principal apuntando al centro de cada bounding box. El secreto para acertar es la consistencia: mismo viewport, mismo scroll.

Concepto principal

El cursor es global (se anima en la timeline principal, no por escena), con el hotspot en la punta. La punta se desliza hasta el centro del cuadro del objetivo y, al hacer clic, activa pulse + ripple. Como el cuadro y el shot provienen del mismo viewport y scroll, la punta cae exactamente sobre lo que aparece en pantalla.

Conceptos clave
🌐
Cursor global
Timeline principal
📍
Hotspot al final
Cae en el centro
💥
Pulse + ripple
Al hacer clic
🎯
Mismo desplazamiento
El box coincide con el shot
💡
La consistencia entre captura↔coordenada es la regla de oro

Siempre que la captura de pantalla de ese paso y el bounding box del objetivo provengan del mismo viewport y del mismo desplazamiento, el cursor estará alineado. Romper esa consistencia es la causa n.º 1 de que el cursor quede «fuera de lugar».

📋 Resumen del Módulo 1.2

Lo que aprendiste
  • ✓ El render de HyperFrames es determinista: no hay red
  • ✓ Por eso nunca se carga el sitio en vivo en el video
  • ✓ Se capturan screenshots reales ANTES, 1 por estado
  • ✓ El viewport fijo se convierte en el espacio de coordenadas
  • ✓ Los bounding boxes vienen de getBoundingClientRect (relativos al viewport)
  • ✓ El cursor apunta a los cuadros; la consistencia entre shot y coordenadas es la regla
Próximo módulo
1.3
🧰 El stack sin clave de API
Las tres piezas locales que ponen en práctica el principio: agent-browser para capturar, HyperFrames para renderizar y Kokoro TTS para narrar — todo en la máquina.
Ir al módulo 1.3 →