Grabación de Videos Demo (gratuito, automatizado)
Crea videos de demostración de producto silenciosos de la aplicación real mediante la automatización de un navegador y luego renderizando un mp4. Gratuito y local: Playwright controla la aplicación, ffmpeg genera el video. Sin SaaS de pago, sin narración, sin clics humanos. El mismo script también funciona como prueba de humo UX, y se regenera cuando la interfaz de usuario cambia — lo que lo convierte en la forma sostenible de producir muchas demostraciones de funcionalidades.
Cuándo usar
- El usuario quiere uno o varios videos de demostración de funcionalidades / recorridos y no quiere pagar por una herramienta.
- El problema recurrente de "alguien tiene que grabar la pantalla para cada nueva funcionalidad".
- Prueba visual rápida de que una funcionalidad funciona, de principio a fin, en la interfaz real.
No es para: videos de marketing con muchas animaciones y voz en off (usa un editor real), ni nada que requiera una persona reaccionando en cámara.
La estructura
iniciar sesión → controlar la app con Playwright (graba .webm) → ffmpeg → .mp4
Tres archivos se colocan en el repositorio de destino bajo demo/ (copia desde resources/):
record.mjs— el motor. Un bloque CONFIG (específico del repositorio) + un mapa FLOWS (una entrada por video).polish.sh—.webm→.mp4, recorta el inicio de sesión, subtítulos opcionales.run.sh— un comando: apunta el dev a staging, graba, pule, limpia.README.md— uso por repositorio.
Para crear un nuevo video: copia una entrada de FLOWS, cambia la url + steps. Eso es todo el ciclo.
Lista de verificación de configuración (haz esto una vez por repositorio)
- Instala las herramientas (una vez):
npm install -D @playwright/test && npx playwright install chromium. Necesitasffmpeg(Homebrew). Para subtítulos incrustados necesitas un ffmpeg compilado conlibfreetype; de lo contrario, los subtítulos se omiten automáticamente y todo lo demás funciona. - Descubre los detalles del repositorio y completa el bloque CONFIG en
record.mjs:- Comando de desarrollo — cómo se ejecuta la aplicación localmente (
npm run dev, a menudo en un subdirectorio comocongrats/). - Ruta del módulo del cliente Supabase — normalmente
src/integrations/supabase/client.ts. El grabador lo importa en la página para iniciar sesión (ver error común 1). - Qué base de datos usar para grabar — usa staging, nunca producción (sin datos personales de usuarios reales). Encuentra su URL + clave anónima/pública + clave de servicio + una URL directa de la base de datos. En esta organización están en el archivo
.env.localdel repositorio de audición (VETTED_SUPABASE_*para staging de VettedAI,STAGING_CONGRATS_SUPABASE_*para staging de Congrats). - Un correo electrónico de inicio de sesión — una cuenta sintética/de prueba que posea datos demostrables. Pregunta siempre al usuario qué cuenta antes de iniciar una sesión (regla del proyecto: no realizar pruebas con usuarios reales sin permiso).
- Rutas — las rutas de enlace profundo para los flujos que grabarás.
- Comando de desarrollo — cómo se ejecuta la aplicación localmente (
- Apunta el servidor de desarrollo local a staging (ver error común 2).
- Crea un flujo, ejecuta
bash demo/run.sh <flujo>, verifica extrayendo fotogramas (error común 8).
Errores comunes (los más difíciles de superar — léelos antes de depurar)
1. Inicia sesión a través del PROPIO cliente de la aplicación, no falsificando localStorage
Supabase-js escribe su sesión bajo una clave/envoltura no predeterminada en el navegador; inyectar manualmente
localStorage['sb-<ref>-auth-token'] = JSON.stringify(session) parece correcto pero el cliente no lo leerá →
la aplicación redirige a /login. En su lugar: inicia una sesión desde el servidor (admin generateLink → verifyOtp proporciona
access_token+refresh_token, sin necesidad de contraseña), luego en la página importa el cliente de Supabase de la aplicación
y llama a supabase.auth.setSession({access_token, refresh_token}). Esto escribe el almacenamiento correcto y la
sesión sobrevive a la navegación. Este es el paso más importante.
2. --mode staging puede ignorarse silenciosamente → usa .env.development.local
vite-react-ssg dev (y algunas configuraciones) ignoran --mode para la carga de archivos de entorno, por lo que .env.staging nunca se carga y
la aplicación sigue apuntando a producción (verás solicitudes al host de Supabase de producción). Vite siempre carga automáticamente
.env.development.local en modo desarrollo con mayor prioridad que .env/.env.local. Por lo tanto, run.sh copia tu configuración
de staging en .env.development.local para la grabación, y luego lo elimina al salir (de lo contrario, cada futuro
npm run dev estaría silenciosamente en staging — un verdadero problema). Los repositorios con vite simple pueden respetar --mode; prueba observando
qué host de Supabase llama la aplicación.
3. El esquema de staging puede estar desactualizado respecto al frontend → reconciliación aditiva dirigida
Una rama de staging puede carecer de columnas recientes que el frontend selecciona → la consulta de datos da error 400
(columna X no existe) y la pantalla se renderiza vacía. No rehagas las migraciones. Compara las columnas de las
pocas tablas que la pantalla lee (staging vs producción a través de information_schema.columns), y aplica solo las que faltan
como aditivas, anulables ALTER TABLE ... ADD COLUMN IF NOT EXISTS. Obtén la aprobación del usuario — es un cambio en la base de datos de staging.
4. Los datos de semilla pueden estar en la escala incorrecta
Los puntajes/valores de la semilla sintética pueden no coincidir con lo que espera el formateador de la interfaz de usuario (por ejemplo, puntajes almacenados de 0 a 100 mientras que la
interfaz hace valor/5*100 → "1392%"). Verifica el rango esperado del formateador comparándolo con los valores reales de producción; reescala los
datos de semilla si es necesario (pregunta primero — es una mutación de datos).
5. Los videos de Playwright no muestran el cursor del ratón
Inyecta una superposición de cursor falsa mediante addInitScript (un punto que sigue al mousemove y crece en mousedown).
La plantilla ya hace esto. Mueve el ratón a las coordenadas reales antes de hacer clic para que se vea.
6. ffmpeg puede carecer de drawtext
Las compilaciones sin libfreetype dan error con subtítulos incrustados. polish.sh detecta drawtext y omite el subtítulo si
falta — no dejes que un error de subtítulos bloquee el mp4.
7. Recorte automático del inicio de sesión/arranque
La grabación captura el inicio de sesión + arranque de la aplicación (segundos muertos). record.mjs mide el inicio y escribe un
archivo .trim acompañante; polish.sh lo corta (ffmpeg -ss).
8. Verifica con fotogramas, nunca con "se grabó"
ffmpeg -ss <t> -i out.mp4 -frames:v 1 frame.png en varios momentos y mira realmente. Las primeras ejecuciones
caerán en /login, un esqueleto o la pestaña incorrecta; los fotogramas son cómo lo detectas.
9. Seguridad de datos y autenticación
Graba en staging con datos sintéticos (por ejemplo, seed_…@test.vetted.com), nunca en el proyecto de un cliente real
(datos personales). Pregunta siempre al usuario con qué cuenta iniciar sesión. Iniciar una sesión de autenticación es una acción real — confírmalo primero.
Creación de un flujo
En record.mjs, FLOWS es un mapa de { label, url, steps(page, ui) }. Los ayudantes ui cubren la mayoría de las necesidades:
ui.settle(what, [words])— espera contenido (networkidle + una palabra que demuestre que la pantalla cargó)ui.scrollThrough(fraction, steps)— desplazamiento suave hacia abajo y hacia arribaui.clickFirstCandidate()/ generalizado aui.clickFirst(selectors)— clic de mejor esfuerzo, nunca falla duroui.beat(ms)— una pausa deliberada para que el video se lea bien
Mantén los flujos con pocos selectores y de mejor esfuerzo (try/catch en los clics) para que un selector perdido se degrade a "un demo de desplazamiento igualmente bueno" en lugar de un bloqueo. Dale un ritmo generoso (pausas de 800–1800ms); un buen demo silencioso dura entre 15 y 35 segundos.
Salida y entrega
El mp4 se guarda en demo/output/ (en .gitignore). open demo/output/<flujo>.mp4 para reproducirlo (un enlace de markdown relativo
no se reproducirá en un IDE — abre el archivo en el editor). Comparte la ruta o ejecuta open para el usuario.
Propagación de esta habilidad (vive en skill-master)
Esta habilidad es canónica en submodules/skill-master/.agent/skills/recording-demo-videos/ y está enlazada simbólicamente en cada
repositorio bajo .agent/skills/. Después de editarla, haz commit+push del submódulo primero, luego del puntero del repositorio padre, y
ejecuta /distribute-skill para actualizarla en los repositorios hermanos (pregunta al usuario antes de hacer push). Consulta
la regla skill-master-submodule-sync.