Communitygithub.com

product-demo-video

Genera videos cortos de demostración de producto (MP4 + GIF) controlando el navegador con Playwright y componiendo la escena con Remotion: zoom in/out automático en el elemento clickeado, cursor animado, subtítulos, transiciones y recorte de tiempo muerto. Úsalo SIEMPRE que el usuario pida demostración de funcionalidad, video de producto, screencast, grabación de pantalla, walkthrough, tutorial en video o GIF de funcionalidad para README/landing/changelog/docs.

¿Qué es product-demo-video?

Este skill te permite crear demostraciones de producto de alta calidad que parecen videos de lanzamiento de SaaS, no simples screencasts. En lugar de grabar la pantalla, captura screenshots en alta resolución con las coordenadas reales de los elementos usando Playwright, y luego anima ese material con Remotion. Esto te da control total sobre la cámara, el ritmo y los subtítulos, y permite re-renderizar en 10 segundos si el usuario pide cambios. El skill soporta múltiples formatos de salida (MP4 1080p, GIF, video cuadrado) y funciona con cualquier flujo que puedas describir en un JSON de guión. Es ideal para crear walkthroughs, demostraciones de funcionalidades, GIFs para README y videos para landing pages o changelogs. El flujo típico incluye escribir un guión JSON, capturar las escenas con Playwright, renderizar el video con Remotion e iterar rápidamente cambiando solo lo necesario.

Compatible con✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/pedroantunes-84/skill-product-demo-video/tree/main/skills/product-demo-video

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Vista previa

Del README del skill

product-demo-video preview

Documentación

Product Demo Video

Demostraciones de producto que parecen videos de lanzamiento de SaaS, no screencasts.

La idea central: no grabes la pantalla. Captura screenshots en alta resolución + las coordenadas reales de los elementos con Playwright, y luego anima ese material en Remotion. Esto te da control total sobre la cámara, el ritmo y los subtítulos — y permite re-renderizar en 10s cuando el usuario diga "más rápido", "zoom más grande", "quita este paso", "haz una versión de 10s". Regrabar sería lento y daría un resultado peor.

Flujo

  1. Setup (una vez por proyecto) → node <skill>/scripts/setup.mjs
  2. Guión → escribe demo.json (ver references/roteiro.md)
  3. Captura → node .demo-video/tools/capture.mjs demo.json capture/ (Playwright)
  4. Render → node .demo-video/tools/render.mjs --capture capture/ --out out/ (Remotion)
  5. Entrega → out/<nombre>.mp4 (1080p) + out/<nombre>.gif (embedable en HTML)
  6. Iterar → edita demo.json y ejecuta solo el paso que cambió

¿Cambió tiempo/cámara/subtítulo? Solo re-render (paso 3, ~30s). ¿Cambió el flujo en la app? Re-captura también (paso 2).

Del pedido en portugués al guión

El usuario describe el flujo en lenguaje natural ("muestra cómo crear un agente"); quien traduce eso en selectores eres tú, mirando la app — nunca adivinando. Adivinar #submit cuesta una captura entera que falla en la escena 4.

  1. Abre la pantalla con las herramientas de navegador y lee el DOM.
  2. Recolecta los selectores en orden de robustez: [data-testid=...] > #id > texto visible (text=Nuevo agente) > ruta CSS. La ruta CSS se rompe al primer cambio de layout; el texto se rompe cuando traducen la interfaz.
  3. Confirma el flujo con el usuario antes de capturar — muéstrale el guión y pregúntale si el orden de los pasos es ese. Él conoce el producto; tú no.
  4. Si la app requiere inicio de sesión, pídele que ejecute auth.mjs primero.

Cuando no sea posible abrir la app (producto interno, sin acceso), pide los selectores o una captura de pantalla con el HTML — es más rápido que adivinar.

El guión es la fuente de la verdad

Un único JSON dirige Playwright y Remotion. Antes de capturar cualquier cosa, escribe el guión y muéstraselo al usuario — es barato corregir ahí y caro corregir después. Esquema completo en references/roteiro.md.

{
  "name": "crear-agente",
  "url": "https://app.ejemplo.com",
  "viewport": { "width": 1600, "height": 900 },
  "scenes": [
    { "action": "goto",  "value": "/dashboard", "camera": "wide", "caption": "Tu panel", "duration": 2 },
    { "action": "click", "target": "[data-testid='new-agent']", "camera": "zoom", "caption": "Crea tu agente", "duration": 2 },
    { "action": "type",  "target": "#agent-name", "value": "Analista Financiero", "camera": "focus", "duration": 2.5 },
    { "action": "click", "target": "button[type=submit]", "camera": "zoom", "duration": 1.5 },
    { "action": "wait",  "value": 1200, "camera": "wide", "caption": "Listo en 3 clics", "duration": 2.5 }
  ]
}

Setup (primera vez en el proyecto)

node "$HOME/.claude/skills/product-demo-video/scripts/setup.mjs"

Crea .demo-video/ (composición Remotion + las herramientas en .demo-video/tools/), instala las dependencias y descarga Chromium — ~300MB. Confirma con el usuario antes de ejecutar; después de eso, capturar y renderizar toman segundos. Sugiere agregar .demo-video/, capture/ y .auth/ al .gitignore.

Para afinar el resultado viéndolo en vivo, cd .demo-video && npx remotion studio abre una vista previa con scrubber — mucho mejor que renderizar para comprobar el timing.

Dirección de cámara

Lo que separa una demo buena de una mala es el ritmo, no el efecto. Reglas que funcionan:

  • Abre y cierra en wide. El espectador necesita situarse antes del zoom y ver el resultado después. Zoom en toda la película cansa y desorienta.
  • Un zoom por intención, no por clic. Clics seguidos en la misma región = una sola escena en zoom. Zoom-in/zoom-out en cada clic da mareo.
  • focus solo para escritura. El campo de texto debe ser legible; un botón no.
  • 2 a 3 segundos por escena. Menos de 1.5s nadie lee el subtítulo; más de 4s se convierte en tiempo muerto. Una demo buena tiene 15–25s y 5–8 escenas.
  • El subtítulo es etiqueta, no frase. "Crea tu agente", "Conecta tus datos". Máximo ~4 palabras, verbo al inicio, sin punto final. No toda escena necesita uno.
  • Corta tiempo muerto en el origen. Loading, redirect, animación de entrada: usa settle en la escena en vez de dejar segundos parados en el video.

La cámara es continua entre escenas (interpolada con easing), por lo que el movimiento ya sale suave — no intentes compensarlo en el guión con escenas extra.

La capa de texto es la narración

No existe audio (GIF no tiene, y el video en feed se reproduce mudo). Quien cuenta la historia es la tipografía, y solo funciona si tiene jerarquía: si todo el texto tiene el mismo peso, el espectador no sabe qué es paso y qué es argumento.

estilorolcuándo
title (escena)apertura/cierre en pantalla completa, con sub1 al inicio, a veces 1 al final
heroel giro — grande, centrado, sobre gradientecomo máximo 1 por demo
labella etiqueta del paso (por defecto), con sub opcionalen la mayoría de las escenas
statnúmero que justifica el producto: "22s", "3 clics"1 al cierre
notedetalle secundario, discretocuando el paso necesita una aclaración

Dos reglas que sostienen el resto: un hero por demo (dos se convierten en ninguno), y el stat cierra — el número grande es lo último que queda en la cabeza de quien ve. Para una demo ejecutiva, el arco suele ser title → labels → hero en el momento decisivo → stat al final.

"highlight": true oscurece toda la pantalla excepto el elemento de la escena. Es el arma más fuerte del conjunto y por eso la más fácil de arruinar: úsala cuando el espectador necesita llevarse ese elemento, no como decoración. Entra después de que la cámara se asienta y sale solo en el instante de la acción, para no ocultar el resultado.

Credenciales

Nunca pongas contraseña en el demo.json. Dos opciones, en este orden de preferencia:

  1. "auth": { "storageState": ".auth/state.json" } — sesión ya iniciada, generada una vez con node .demo-video/tools/auth.mjs <url> (abre el navegador, el usuario inicia sesión manualmente).
  2. "auth": { "login": { "user": "#email", "pass": "#password", "submit": "button[type=submit]" } } con las credenciales en DEMO_USER / DEMO_PASS en el entorno.

Si la demo muestra datos reales, usa "redact": ["selector"] en el guión para difuminar elementos sensibles antes de la captura — sale difuminado ya en el PNG, no se puede recuperar.

Salidas

FormatoUsoCómo
demo.mp4 1920×1080landing, LinkedIn, YouTubepor defecto
demo.gif 960×540README, docs, correo, HTML--formats mp4,gif (por defecto)
demo-square.mp4 1080×1080Instagram/feed--formats mp4,square

GIF pesa. El render.mjs ya usa palettegen (paleta dedicada al video) a través del ffmpeg que viene integrado en Remotion — no necesitas instalar nada. Aún así, 15s a 960px dan ~3.5MB; para README prefiere --gif-width 720 --gif-fps 12, que reduce a menos de 1.5MB.

Para embeber en HTML: <img src="demo.gif" width="720" alt="...">. Si el usuario acepta MP4, <video autoplay loop muted playsinline> pesa ~10x menos.

Probar la instalación sin tocar el producto

assets/ejemplo/ trae una app falsa (app-ejemplo.html) y el guión correspondiente, ejercitando todas las acciones — title, shot, click, type, select, hold, redact. Ejecutar esto primero separa "el skill está roto" de "el selector de la app está mal", que es la duda cara cuando algo falla en la primera demo real.

Cuando algo sale mal

  • Selector no encontrado → capture.mjs falla en la escena y dice cuál. Pídele al usuario la URL/pantalla e inspecciona con el navegador antes de adivinar otro selector.
  • Zoom borroso → aumenta scale a 3 en el guión (screenshots 3×) o reduce el zoom.
  • Video desincronizado del subtítulo → duration de la escena es lo que manda; ajústalo ahí.
  • Detalles de composición, cámara, cursor y personalización visual: references/remotion.md.

Skills relacionados