Demo narrado
Un agente, una tarde, un .mov que un VP puede ver en el móvil. La receta (probada en cinco clips, 69–188 s cada uno):
- Entrevista al usuario — cinco preguntas, no más (abajo). Redacta la historia desde el contexto que ya tienes; el usuario edita, no escribe.
- Escribe una especificación de escenas (
clips/<nombre>.yaml): 4–8 escenas, ~25–45 palabras de narración cada una (≈ 10–18 s hablados). Cada escena tiene un momento culminante — el instante en que aparece lo importante — y el video se corta para que ese momento se muestre al principio, no al final. - Renderiza:
scripts/render_clip.py clips/<nombre>.yaml. Por escena: TTS → captura → ajustar video al audio → subtitular → multiplexar; luego concatenar. - Revisa las imágenes fijas que escribe el renderizador (
out/_<clip>_<scene>.png) con la herramientareadantes de declarar terminado. Vuelve a renderizar escenas individuales con--only s2. - Publica (opcional):
scripts/slack_post.py <channel_id> out/<clip>.mov "<descripción>".
Todo es re-ejecutable y está en caché (TTS por hash de texto, video por escena), así que iterar sobre una frase cuesta segundos.
1. La entrevista (haz estas preguntas, luego redacta)
Haz las cinco en un solo mensaje; acepta respuestas parciales y completa el resto desde el contexto, etiquetando lo que asumiste.
- ¿Para quién es y cuánto tiempo tienen? (ingeniero colega 3 min · ejecutivo 90 s · desplazamiento en Slack 60 s) → define el número de escenas y el ritmo.
- ¿Qué es lo único que deberían creer después de verlo? → se convierte en la primera frase de la escena 1 y la última frase de la última escena.
- ¿Qué debe aparecer en pantalla? (una interfaz, una terminal, un documento, un gráfico, un archivo) → decide los tipos de captura. Pide URLs / comandos / rutas.
- ¿Cuál es el momento 'en vivo'? Algo que ocurra visiblemente (una consulta que devuelve resultados, una compilación que termina, un número que aparece). Mínimo uno por clip.
- ¿Voz y tono? Por defecto:
onyx, "narración de demo técnica tranquila, clara y segura, ritmo medio, énfasis ligero en los números". Ofrecealloy/novasi quieren algo más ligero.
Luego propón el storyboard como tabla (escena · qué hay en pantalla · resumen de la narración en 1 línea · momento culminante) y obtén una aprobación antes de renderizar. Renderizar un clip de 5 escenas lleva ~3–6 min; no renderices antes de la aprobación.
2. Especificación de escenas
clip: 1-configuracion # nombre de salida → out/1-configuracion.mov
tamaño: 1440x900 # opcional: marco común para todas las escenas (ajustar + rellenar) — establécelo al mezclar escenas de pantalla y navegador
voz: onyx
instrucciones: "Narración de demo técnica tranquila, clara y segura. Ritmo medio, pausas naturales en los puntos. Énfasis ligero en los números."
escenas:
- id: s1 # ids cortos y estables → claves de caché
caption: "Tesis · un gráfico, cuatro evidencias" # tercio inferior; mantener ≤ 60 caracteres
narracion: "…25–45 palabras…" # escribe los números como palabras si el TTS los distorsiona ("dieciocho mil")
# exactamente una fuente de captura por escena:
url: "http://127.0.0.1:4300/#mode=purchase" # (a) navegador vía Playwright — más acciones opcionales:
acciones: # se ejecutan después de cargar, en orden; `ready` marca el momento culminante
- rellenar: ["#prompt", "Acne Studios"]
- presionar: ["#prompt", "Enter"]
- esperar: ".layer-chip" # selector (timeout 45 s) → establece ready
- hacer_click: "button:has-text('fit')"
- seleccionar: ["#graph-layout", "brand"]
- desplazar_a: "#join" # scrollIntoView (para documentos largos) → establece ready
- pasar_ratón: ".card"
# video: "cache/cr_s3" # (b) directorio pregrabado (page.mov + marks.json) o un archivo — ver record_screen.sh
# still: "docs/figura.png" # (c) una imagen estática (gráfico, diapositiva) — sin Ken-Burns, mantenida para la narración
pausa: 2 # segundos extra después de la última acción
velocidad: 1 # pre-acelerar la fuente (8 = un desplazamiento lento mostrado a 8×)
escala: 2560 # ancho de reducción por escena (grabaciones de pantalla); fuente: 28 = tamaño de caption en píxeles para esta escena
Reglas que hicieron buenos los clips:
- El momento culminante primero. El renderizador comienza cada escena ~2.5 s antes de
ready, rellena el último fotograma si la narración es más larga, recorta si es más corta. Una escena cuyo momento culminante está en el segundo 40 de una grabación de 45 s se convierte en una escena de 12 s que abre con ese momento. - Narración y pantalla coinciden. Cada nombre en mayúsculas y cada número en la narración debe ser visible o estar a punto de ser visible. Elimina frases que no lo estén.
- Una idea por escena. Si una frase comienza con "además", es una nueva escena o se elimina.
- Los subtítulos son el esquema. Leer solo los subtítulos debería dar toda la historia.
- Nunca inventes un número para la narración. Tómalo de un archivo de resultados o de una respuesta en vivo que acabas de hacer; di "aproximadamente" si redondeas.
3. Fuentes de captura
- Navegador (
url+acciones) — Playwright Chromium, 1440×900, sin cabeza, graba webm. Necesita un proyecto Node con@playwright/testy Chromium instalado; establecePW_REPO=/ruta/a/ese/proyecto(por defecto: el propiopw/del skill — ejecutascripts/setup.shuna vez para crearlo). - Pantalla / terminal (
video) —scripts/record_screen.sh <escena> <segundos> [--rect x,y,ancho,alto] -- <comando…>: iniciascreencapture -V, ejecuta tu comando, escribemarks.jsonconstarted(ms) cuando el comando señala el momento culminante imprimiendoMARK. Problema:screencapture -Vsolo avanza cuando los píxeles cambian; un panel de terminal estático congela la grabación. Mantén algo parpadeando (una línea de reloj de 1 Hz) o usashow_file.shque pagina un archivo con un reloj. Reduce la escala de capturas anchas conDEMO_SCALE=2560. Privacidad: graba un rectángulo (--rect, en puntos;screencapture -R) para capturar solo el panel deseado — sin título de ventana, barra de pestañas, barra lateral, dock, notificaciones ni ventanas de fondo. Antes de publicar, lee cada imagen de revisión y pregúntate: ¿hay algo en pantalla que identifique a un empleador, un host, una URL interna, otra persona? Neutraliza el texto que paginas (show_file.sh) — es la demo, no tus archivos reales. - Imagen estática (
still) — un PNG/JPG mantenido para la narración; úsalo para gráficos, tablas, una diapositiva. - Pregrabado (
video: archivo.mov) — conready: <segundos>en la escena.
4. Renderizar, revisar, publicar
export OPENAI_API_KEY=… # TTS (gpt-4o-mini-tts); o TTS_URL=https://<proxy>/v1/audio/speech TTS_API_KEY=… para un proxy compatible
scripts/render_clip.py clips/1-configuracion.yaml # clip completo → out/1-configuracion.mov (+ out/_1-configuracion_<escena>.png imágenes fijas)
scripts/render_clip.py clips/1-configuracion.yaml --only s2 # re-renderizar una escena, re-concatenar
DEMO_FONT=26 scripts/render_clip.py … # tamaño de subtítulo (22 para 1440 px, 26–30 para fuentes de 2560 px)
Revisión: read dos o tres de las imágenes fijas out/_*.png. Si una escena del navegador registra wait failed: … Timeout, la app estaba lenta o el selector cambió: la escena aún se renderiza desde t=0 (sin corte de momento culminante) — corrige el selector o simplemente vuelve a ejecutar esa escena con --only <id> cuando la app esté inactiva (fotograma de apertura de cada escena) — verifica que el subtítulo sea legible, el momento culminante esté en pantalla,
nada sensible sea visible (tokens, filas de nivel de comprador, mensajes de otras personas). Mira los primeros y últimos 5 s del .mov si puedes.
Publica en Slack con una descripción de ≤ 3 líneas: qué muestra · duración · un número. scripts/slack_post.py C0123… out/1-configuracion.mov "…" usa las
credenciales de la sesión del navegador slack-mcp en ~/.config/slack-mcp/credentials.json; si faltan, entrega al usuario el archivo y la descripción.
5. Convenciones (mantén el proyecto ordenado)
clips/ especificaciones · cache/ TTS + video por escena (ignorado por git) · out/ finales + imágenes fijas · blurbs/ texto de Slack. Nombra los clips en orden de reproducción
(0-…, 1-…, 2a-…). Mantén un storyboard.md con la tabla de la entrevista; es el artefacto que la gente pide después del video.
Dependencias: ffmpeg/ffprobe, node ≥ 18, Playwright Chromium (para escenas de navegador), screencapture de macOS (para escenas de pantalla), una clave TTS.
scripts/setup.sh verifica e instala lo que puede.