Communitygithub.com

lyonsv/demo-video-skill

Graba videos de demostración pulidos y con guion de una aplicación web (recorridos de producto, animaciones de arquitectura antes → después, segmentos de funciones) como MP4s de 1440×900 en un formato consistente — tarjetas de título blancas, leyendas en píldora, ondas de clic, esperas aceleradas — utilizando Playwright en Chrome sin interfaz gráfica y codificando con ffmpeg.

¿Qué es demo-video-skill?

Este skill permite crear videos de demostración profesionales y consistentes de aplicaciones web, ideales para presentaciones a stakeholders o documentación de producto. Utiliza Playwright para controlar Chrome sin interfaz gráfica, grabando interacciones reales con la aplicación, y ffmpeg para codificar el video final en formato MP4 a 1440×900. El skill genera automáticamente tarjetas de título y final blancas, leyendas descriptivas en píldora oscura, ondas de clic moradas y acelera automáticamente las esperas (como respuestas de modelos o procesos largos) para mantener un ritmo ágil. Está diseñado para ser usado en cualquier situación donde se necesite un video de demostración, ya sea un recorrido completo del producto, una animación de arquitectura, o un segmento específico de una funcionalidad. El skill organiza los videos en un repositorio dedicado de demos, con un manifiesto JSON que describe segmentos, dependencias y salida, permitiendo reutilizar y combinar segmentos fácilmente.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lyonsv/demo-video-skill/tree/HEAD

Preguntar en tu IA favorita

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

Documentación

Videos de demostración

Recorridos con guion grabados desde la aplicación real en ejecución. El espectador ve el producto haciendo trabajo real; las partes lentas (respuestas del modelo, trabajos) se aceleran, y cada momento tiene una breve leyenda que indica qué observar. Se utiliza el mismo formato cada vez para que los segmentos se puedan unir en un solo video.

El formato de la casa

Mantén estos valores exactos, para que los nuevos segmentos coincidan con los anteriores:

  • Video: 1440×900, 30fps, H.264 (libx264 -preset slow -crf 18), yuv420p, +faststart, sin audio.
  • Tarjetas de título y final: pantalla blanca completa, centrado: una línea opcional pequeña de marca en gris mayúscula (establece brand en kit.start; ninguna por defecto), título en negrita de 46px, subtítulo gris de 20px. Dura aproximadamente 2.8s, luego se desvanece. Los segmentos abren con una tarjeta de título; el último termina con una tarjeta de conclusión de una línea (por ejemplo, "Idea → evaluación → prueba en vivo → implementación" / "Sin implementación de la aplicación en el medio").
  • Leyendas: píldora oscura (rgba(17,17,17,.88)), Lato seminegrita blanco de 17px, centro inferior. Una idea por leyenda, aproximadamente 60 caracteres o menos, mayúscula inicial, sin punto final, tiempo presente, escrito desde la perspectiva del espectador ("Los resultados se abren como un artefacto junto al chat"). Cambia la leyenda cuando cambie el momento; mantén cada una durante aproximadamente 2.5–4s.
  • Clics: una onda púrpura (rgba(122,71,255,…)) aparece en el objetivo justo antes de cada clic.
  • Escritura: visible, tecla por tecla (aproximadamente 25ms por tecla; 14ms para texto largo).
  • Esperas: cualquier cosa lenta se ejecuta dentro de ff(), que se reproduce en aproximadamente 2s. Todo lo demás es en tiempo real.
  • Escenas de arquitectura: una página blanca fija de 1440×900 de escenas (título → antes → problema resaltado → después → conteo de métricas → lista de funciones), Lato, tinta #111, acento púrpura #6f43d6; etiquetas "antes" en gris, etiquetas "después" en púrpura. assets/architecture-example.html es la referencia: reutiliza su CSS y estructura y cambia el contenido.

Dónde viven los videos: el repositorio de demos

Cada video tiene una carpeta en el repositorio de demos del equipo (por defecto ~/src/demos, o $DEMOS_REPO), que contiene sus scripts de grabación y un manifiesto demo.json. Los repositorios de producto permanecen libres de código de demostración. Las grabaciones nunca se confirman; el campo output del manifiesto indica dónde va el MP4.

~/src/demos/
  package.json            playwright-core + ffmpeg-static (npm install una vez)
  <video>/
    demo.json             manifiesto
    architecture.html     segmento de "escenas" (opcional)
    record-<part>.js      segmentos de "recorrido", escritos en demo-kit
    .build/               MP4s y fotogramas por segmento (gitignorado)

Manifiesto (demo.json):

{
  "name": "<nombre-del-video>",
  "title": "Una línea: qué muestra el video",
  "description": "Para quién es y el punto que demuestra",
  "owner": "correo",
  "repos": ["repositorios donde viven las funciones grabadas, con ramas"],
  "needs": [{ "what": "servicio", "check": "URL que responde 2xx/3xx cuando está activo", "start": "cómo iniciarlo" }],
  "reset": "cómo obtener una toma limpia, y qué deja la grabación",
  "segments": [
    { "name": "architecture", "kind": "scenes", "page": "architecture.html", "timeline": "0:3000,1:4500" },
    { "name": "walkthrough", "kind": "walkthrough", "script": "record-walkthrough.js" },
    { "name": "intro", "kind": "video", "file": "~/ruta/a/existing.mp4" }
  ],
  "output": "~/Downloads/<nombre>.mp4"
}

La carpeta examples/sift/ de este skill es una carpeta de referencia: un video de dos segmentos (una página de escenas y un recorrido real) de una pequeña aplicación de ejemplo que se incluye en la misma carpeta.

Si el repositorio de demos aún no está clonado, créalo (git init, el package.json anterior, y un .gitignore que cubra node_modules/, .build/, *.mp4, *.jpg, *.png, *-frames/ y *-timeline.json) e informa al usuario que aún no tiene remoto.

Herramientas (en scripts/, relativo a este skill)

ScriptQué hace
find-demos.jsnode find-demos.js [raíz…] [--json]: lista cada video en el repositorio de demos, con segmentos, repos, salida, y cuándo se grabó y confirmó por última vez.
record.jsnode record.js <directorio-video> [--only <segmento>]: verifica needs, graba y codifica cada segmento en .build/, los une en output (el video anterior se conserva como *.previous.mp4). Ejecútalo desde la raíz del repositorio de demos.
demo-kit.jsBiblioteca para scripts de recorrido: kit.start() proporciona page, title/untitle, caption, tap, type, ff, scroll/scrollTop, ripple, navigate, startCast, finish. Los fotogramas se transmiten al disco.
encode.jsnode encode.js <directorio-fotogramas> <timeline.json> <out.mp4>: construye el MP4, comprimiendo ventanas de ff().
record-scenes.jsnode record-scenes.js <pagina.html> <out.mp4> "0:3000,1:4500,…": graba una página de escenas que define window.step(n).
concat.jsnode concat.js <out.mp4> <a.mp4> <b.mp4> …: une segmentos, recodificando al formato de la casa.
review.jsnode review.js <video.mp4> <directorio-salida> [fotogramas] [at=s,s,…]: hojas de contacto 2×2 de fotogramas para revisar.

assets/example-walkthrough.js es un ejemplo completo trabajado en el kit (y examples/sift/record-walkthrough.js es uno real). Léeelo antes de escribir un nuevo recorrido; muestra la estructura, incluyendo cambiar de aplicación a mitad del video, trabajos acelerados y una tarjeta final.

Flujo de trabajo

0. Encuentra lo que ya existe

Ejecuta find-demos.js primero. Si el usuario quiere volver a grabar o extender un video que ya tiene una carpeta, trabaja en esa carpeta: vuelve a grabar con record.js <carpeta> (o --only <segmento> después de un cambio de UI), o añade un segmento a su manifiesto. No inicies una segunda carpeta para el mismo video. Crea una nueva carpeta solo para un video verdaderamente nuevo, nombrada según él (kebab-case).

1. Guion gráfico primero

Antes de cualquier código, escribe el guion gráfico como una lista numerada de secciones, cada una con sus momentos: quién aparece en pantalla y el título. Decide de antemano:

  • Qué debe ser real, y qué se puede simular. Prefiere lo real (llamadas reales al modelo, búsquedas reales). Si los datos deben simularse (por ejemplo, semanas de tráfico en vivo), indícalo en pantalla, tanto en un título como en la propia aplicación si puede etiquetarlo. Los espectadores toman una demostración al pie de la letra, por lo que un resultado simulado presentado como real es engañoso.
  • Qué no se debe hacer clic. Cualquier cosa que escriba en entornos compartidos (guardar tableros, enviar correo electrónico, compras). Muestra el botón; no lo presiones.
  • Duración: aproximadamente 60–90s por segmento. Un video unido de 3 minutos está bien; cada segmento debe hacer un punto.

Si el objetivo del usuario está claro a partir de la conversación, adelante, comparte el guión gráfico en tu actualización mientras trabajas. Pregunta solo cuando el punto del video no esté claro.

2. Configura la carpeta del video

Crea <repositorio demos>/<video>/ con un demo.json (rellena needs con una URL de check para cada servicio que toque el video, y escribe reset). Ejecuta npm install en la raíz del repositorio de demos si falta node_modules. El kit y los scripts resuelven playwright-core y ffmpeg-static desde el directorio de trabajo, así que ejecuta todo desde la raíz del repositorio. Chrome debe estar instalado (channel: 'chrome'; no es necesario descargar el navegador de Playwright).

3. Verificación previa de la aplicación

  • Confirma que todos los servicios que toca el video estén activos (curl cada URL), y que HTTPS local funcione (el kit ignora los certificados autofirmados).
  • Restablece el estado para que la toma comience limpia (DB nueva, localStorage borrado), y haz que el script falle inmediatamente si el estado está sucio. Una toma que falla 3 minutos después cuesta llamadas reales al modelo y tiempo.
  • Mide los endpoints lentos que sondea el video. Una consulta de resultados de 4 segundos se muestra como un esqueleto de carga en cámara; arregla la consulta o espera a que termine.
  • Captura una imagen de cada estado clave con un pequeño script de Playwright y mírala: diseño, ajuste, imágenes rotas, qué está arriba del pliegue a 1440×900. Esto es más barato que grabar.

4. Escribe el script de grabación

Copia la estructura de assets/example-walkthrough.js:

const kit = require(process.env.DEMO_KIT || `${process.env.HOME}/.claude/skills/demo-video/scripts/demo-kit`);
const demo = await kit.start();                             // record.js proporciona las rutas de fotogramas y timeline
await demo.page.goto(URL, { waitUntil: 'networkidle' });
await demo.title('Nombre de la función', 'Qué permite hacer a las personas');
await demo.startCast();                                     // iniciar después de que el título cubra la página
await demo.sleep(2800); await demo.untitle(); await demo.sleep(900);
await demo.caption('…'); await demo.tap(locator); await demo.type(locator, 'texto');
await demo.ff(() => page.waitForFunction(() => /* respuesta terminada */ true, null, { timeout: 180000 }));
await demo.finish();
  • Usa selectores estables (aria-label, ids, data-*) y verifícalos contra el DOM real.
  • Espera condiciones de finalización reales dentro de ff(), no esperas fijas, con tiempos de espera generosos.
  • Cuando una leyenda habla de algo, desplázalo en pantalla primero (demo.scroll(px, 'main') para aplicaciones cuyo contenido se desplaza dentro de un elemento).
  • demo.navigate(url) cambia de página o aplicación; reinicia la screencast en la nueva página.
  • Para un segmento de arquitectura, construye la página de escenas a partir del ejemplo y grábala con record-scenes.js. También dale navegación por teclas de flecha y espacio (el ejemplo la tiene), para que la misma página funcione al presentar en vivo.

5. Grabar

Desde la raíz del repositorio de demos, ejecuta el video completo (o un segmento) en primer plano con un tiempo de espera largo, registrando la salida:

set -o pipefail; node ~/.claude/skills/demo-video/scripts/record.js <video> [--only <segmento>] 2>&1 | tee <video>/.build/record.log

No lo canalices a tail: oculta el código de salida del grabador, y una toma fallida parece un exito. Si debes ponerlo en segundo plano, espera el PID real (while kill -0 $PID; do sleep 5; done) en lugar de confiar en una notificación de "completado", que puede llegar antes de que finalice el proceso.

6. Revisar

record.js ya codificó y unió todo; imprime el comando de revisión:

node ~/.claude/skills/demo-video/scripts/review.js <output.mp4> <video>/.build/review 16

Para ver un segmento, revisa <video>/.build/<segmento>.mp4.

Lee cada hoja de contacto antes de dar el video por terminado. Verifica que:

  • cada leyenda coincida con lo que está en pantalla en ese momento;
  • lo que menciona una leyenda sea visible, no debajo del pliegue;
  • no haya imágenes rotas ni texto alternativo, esqueletos atascados, toasts de error, encabezados ajustados o recortados, ni interfaz de depuración;
  • las esperas aceleradas parezcan un rápido desenfoque de progreso, no un fotograma congelado;
  • las tarjetas de título y final estén ahí.

Arregla el script o la aplicación (por ejemplo, un marcador de posición para imágenes que no cargan, una consulta más rápida), restablece el estado y vuelve a grabar. Espera dos o tres tomas.

7. Entregar

  • Revisa los puntos de unión: review.js <output> <dir> 0 at=<t-1>,<t+1> en cada límite de segmento.
  • record.js conserva la versión anterior como *.previous.mp4. Nunca sobrescribas videos que no sean el output de esta carpeta: para añadir al video de otra persona, agrégalo como un segmento video de una nueva carpeta.
  • Informa al usuario que la carpeta del video está lista para confirmar en el repositorio de demos. Solo confirma si lo solicita.
  • Reporta al usuario: las rutas de archivo y duraciones, qué muestra cada segmento, qué fue real y qué fue simulado, y cualquier estado que la grabación haya dejado (servicios en ejecución, registros que creó, cualquier cosa que aún esté activada) con cómo deshacerlo.

Errores encontrados antes

  • Memoria: una screencast de CDP envía hasta 60 fotogramas por segundo mientras algo se anima. Almacenar fotogramas en búfer en memoria para una toma de varios minutos mata el grabador sin salida. El kit transmite fotogramas al disco y los reduce durante ff(); mantén eso así.
  • Reloj: las ventanas de ff() y las marcas de tiempo de los fotogramas usan segundos de reloj de pared, así que mide toda la espera (incluyendo el sondeo) dentro de una sola llamada ff().
  • Trabajo bloqueante (por ejemplo, execFileSync para un script de datos) dentro de ff() está bien: los fotogramas se reanudan después y la ventana se comprime de todos modos.
  • Puertos: verifica que un puerto esté libre antes de iniciar un servicio para la demo; no mates procesos que no iniciaste.
  • Estado residual: una demo que termina implementando o habilitando algo lo deja activo. Desactívalo después o informa al usuario.

Skills relacionados