PTENES
MÓDULO 2.2

🗺️ El actions.json

El archivo de entrada de capture.mjs: URL, viewport y la lista de pasos con selectores y narración. Ejecutar node capture.mjs actions.json genera los shots PNG + el steps.json.

7
Temas
~30
Minutos
Práctico
Nivel
Config
Tipo
actions.json URL · VIEWPORT · STEPS { } url viewport window steps[ ] del · target subtítulo · narración capture.mjs ejecuta pasos shots/*.png 1 por estado steps.json bbox + subtítulo node capture.mjs actions.json
1

🧱 Estructura del actions.json

Un JSON con la configuración global y la lista de pasos. Es el guion que capture.mjs ejecuta de principio a fin.

Concepto principal

El actions.json describe toda la demo en un archivo: adónde ir, en qué tamaño, qué hacer en cada paso y qué decir. Un node capture.mjs actions.json y la captura queda lista.

actions.json — ejemplo real (encabezado)
{
"url": "http://localhost:8000/",
"viewport": [1280, 800],
"window": { "top": 96, "titleH": 52, "urlLabel": "localhost:8000" },
"eyebrow": "DEMOSTRACIÓN · INEMAIMG",
"ctaNarration": "Esto es contenido de INEMA punto CLUB...",
"steps": [ ... ]
}
🔗
url
adónde ir
📺
viewport
tamaño fijo
🪟
window
marco
📋
steps[]
los pasos
2

📺 URL + viewport

Dónde y en qué tamaño. El viewport definido aquí es el espacio de coordenadas de todos los bboxes del video.

📊 Qué hace capture.mjs con estos campos
url
Se convierte en agent-browser open <url>. La app debe estar en línea en esa dirección.
viewport [W,H]
Se convierte en set viewport W H antes de open. Ancho ≤ ~1280 para que quepa en 16:9.
💡
Cambia el viewport aquí y cambiará en todo el video

Como el viewport es el espacio de coordenadas de las bboxes, cambiarlo después de capturar rompe la alineación del cursor. Decide el viewport antes de generar las capturas.

⚠️
Las pantallas demasiado anchas desbordan el canvas

Por encima de ~1280 de ancho, la captura sale comprimida o se sale de los bordes del canvas 1920×1080. Reduce el viewport durante la captura en lugar de forzarlo.

3

📋 La lista de pasos

El array steps en orden: cada elemento es un estado de la pantalla. 5–8 pasos + CTA ≈ 35–50s.

El arco de una demo
1
Pantalla inicial (intro:true)

El 1.er paso presenta la app, sin acción — solo la captura de pantalla del estado inicial.

2
Acciones 1, 2, 3...

Cada paso ejecuta un do, captura la pantalla y mide la bbox del target.

3
Resultado (zoom:true) + CTA

El último paso de contenido hace un zoom suave en el resultado. El CTA de INEMA.CLUB viene del composition-template.

💡
Mantén 5–8 pasos

Además, el video cansa y la captura y edición se convierten en un trabajo pesado. 5–8 pasos + CTA dan un walkthrough de ~35–50s.

4

⚙️ El campo do:{type}

La acción ejecutada antes de la captura de pantalla. Sin do, el paso solo captura el estado actual.

do.type Campos Qué hace
fillselector, valorCompleta input/textarea (CSS selector)
clickselectorHaz clic (CSS selector)
clickTexttag, textoHaz clic en el <tag> cuyo texto === text
setValueselector, valorDefine value y activa input/change
waitmsEspera (p. ej., generación lenta)
Ejemplo: hacer clic en el texto del botón
{
"id": "generar",
"del": { "type": "clickText", "tag": "button", "text": "Generar" },
"target": { "tag": "button", "text": "Generar" }, "click": true
}
💡
setValue para campos controlados por JS

Este fue el caso del campo de altura: fill no bastaba. El setValue dispara input+change para que el framework reaccione. (El fill nativo de Playwright está en la hoja de ruta — módulo 2.4.)

5

🎯 El objetivo / selector de cada paso

O target es lo que apunta el cursor. Puede ser diferente del elemento que el do activa.

✓ Formas de target
  • ✓ Selector CSS: "textarea"
  • ✓ CSS por atributo: "input[name=height]"
  • ✓ Por texto: {tag:"button", text:"Gerar"}
  • ✓ capture lee el bbox del target mediante eval
✗ Precauciones
  • ✗ Target sin coincidencia → bbox null + aviso en el log
  • ✗ Evita @eN volátiles en pantallas que cambian
  • ✗ El texto con acentos y espacios debe coincidir exactamente
  • ✗ No confundas el objetivo del clic con el objetivo de la mira
💡
del ≠ target

Puedes completar un campo (do) y apunta al botón de enviar (target). El cursor va al target; la acción ocurre en el do.

6

🗣️ Texto de narración por paso

caption es el subtítulo en pantalla; narration es la voz. Expande los números y las siglas para que la lectura suene natural.

Paso con narración (ejemplo real)
{
"id": "size", "click": true,
"caption": "2 · Elige el tamaño — 512²",
"narration": "Después, elige el tamaño. Vamos con quinientos doce."
}
📊 Ampliar a la voz
"512"
→ «quinientos doce»
"768"
→ «setecientos sesenta y ocho»
"inema.club"
→ «inema punto club»
💡
La narración va al steps.json → Kokoro

El texto de cada paso se escribe en assets/txt/sN.txt y Kokoro (voz pf_dora, --speed 0.98) genera los WAV. El texto fonético produce una voz natural.

7

📦 La salida: steps.json + las capturas PNG

capture.mjs genera las capturas de pantalla y steps.json, el puente entre la captura (T2) y el renderizado (T3).

steps.json — salida (1 paso)
{ "shot": "01-prompt.png",
"target": {"x":129,"y":252,"w":482,"h":96},
"click": false, "caption": "1 · Escribe un prompt detallado" }
📊 Qué se obtiene de la captura
assets/shots/*.png
1 captura real por estado (00-home.png, 01-prompt.png...).
steps.json
viewport, window, eyebrow, CTA y los pasos con bbox + flags + caption + narration.
💡
Es el contrato con el render

O composition-template.mjs (T3) lee steps.json y arma el marco + cursor + resaltado + zoom + CTA, midiendo los WAV con ffprobe: un único timing.

🎯 Resumen del módulo

  • ✓ actions.json = url + viewport + window + steps[] + CTA
  • ✓ el viewport definido aquí es el espacio de coordenadas de las bboxes
  • ✓ do.type: fill / click / clickText / setValue / wait
  • ✓ target = lo que apunta el cursor (selector CSS o {tag,text})
  • ✓ salida: shots/*.png + steps.json (contrato captura→render)
Próximo módulo
2.3
🎯 Coordenadas, selectores y bounding boxes
Cómo la bbox se convierte en el objetivo del cursor en el canvas, los selectores robustos y la región de zoom.
Ir al módulo 2.3 →