Productor Automático de Demos
Produce videos demo narrados profesionales de CUALQUIER aplicación web — automáticamente.
Resumen del Pipeline
Contexto del usuario → Guion de demo → Diapositivas → Narración TTS → Grabación del navegador → MP4 final
Tres fases, completamente automatizadas:
- Narración — edge-tts (Microsoft Neural TTS gratuito) genera audio por escena
- Grabación — Playwright controla Chromium sin interfaz gráfica con captura de video
- Ensamblaje — ffmpeg fusiona video + audio en un MP4 pulido
Cuándo Activar
- El usuario pide "crear una demo", "grabar un tutorial", "hacer un video demo"
- El usuario proporciona una URL + descripción de lo que se debe mostrar
- El usuario quiere un screencast automatizado con voz en off
Flujo de Trabajo Paso a Paso
Paso 1: Recopilar Contexto
Pregunta al usuario por:
- URL objetivo — la aplicación web a mostrar (ej.,
https://miapp.azurewebsites.net) - Qué mostrar — funcionalidades clave, flujos de usuario o escenarios
- Audiencia — ¿quién verá el video? (ejecutivos, desarrolladores, clientes)
- Duración objetivo — ¿cuánto debe durar la demo? (1-5 min típico)
- Preferencia de voz — idioma y género (por defecto:
en-US-JennyNeural) - Marca — nombre del producto, subtítulo, organización, color de acento para intro/outro
Paso 2: Crear Guion de Demo
Genera un archivo demo_script.md usando este formato:
# Demo: {Nombre del Producto}
## intro | 5
> slide intro
Bienvenido a esta demo de Nombre del Producto. Hoy recorreremos las funcionalidades clave.
## login | 8
> goto {base_url}
> fill Usuario [email protected]
> fill Contraseña ****
> click button Iniciar Sesión
Aquí iniciamos sesión en la aplicación usando nuestras credenciales de demo.
## dashboard | 10
> wait 2
> scroll down 300
El tablero muestra una vista general en tiempo real de todos los elementos activos.
## feature_one | 12
> click link Funcionalidad Uno
> wait 1
> scroll down 200
Exploremos la Funcionalidad Uno, que permite crear y gestionar flujos de trabajo.
## outro | 5
> slide outro
¡Gracias por ver! Visítenos en contoso.com para más información.
Reglas del formato del guion:
## scene_id | min_duration_seconds— encabezado de escena> acción args...— acciones de Playwright (ver Referencia de Acciones abajo)- Líneas de texto plano = narración (leída por la voz TTS)
- La narración determina la duración real de la escena (ajustada para coincidir con la longitud del audio)
Paso 3: Generar Diapositivas
Ejecuta el generador de diapositivas para crear archivos HTML de intro/outro:
python generate_slides.py `
--title "Nombre del Producto" `
--subtitle "Tu eslogan aquí" `
--org "Contoso" `
--badge "Con tecnología de Azure" `
--accent "#60a5fa" `
--out-dir ./slides
Paso 4: Instalar Dependencias
pip install edge-tts playwright
playwright install chromium
# Asegúrate de que ffmpeg esté disponible:
# Windows: winget install Gyan.FFmpeg
# macOS: brew install ffmpeg
# Linux: sudo apt install ffmpeg
Paso 5: Ejecutar el Grabador
python record_demo.py `
--script demo_script.md `
--base-url "https://miapp.azurewebsites.net" `
--voice en-US-JennyNeural `
--slides-dir ./slides `
--output demo_final.mp4
Opciones adicionales:
--resolution 1280x720para archivo más pequeño--var project_id=abc123para variables personalizadas en el guion--var [email protected]para flujos parametrizados
Paso 6: Revisar e Iterar
Después de grabar, revisa el video resultante. Ajustes comunes:
- ¿Demasiado rápido? Aumenta
min_durationen los encabezados de escena - ¿Tiempos incorrectos? Agrega acciones
> wait Nentre pasos - ¿Faltan pasos? Agrega más escenas al guion
- ¿Voz incorrecta? Prueba una voz diferente de edge-tts
Referencia de Acciones
| Acción | Sintaxis | Descripción |
|---|---|---|
goto | > goto https://url.com | Navegar a una URL |
slide | > slide intro | Mostrar diapositiva HTML desde el directorio de diapositivas |
click | > click link Texto del Enlace | Hacer clic en un enlace por texto |
click | > click button Texto del Botón | Hacer clic en un botón por texto |
click | > click text Cualquier Texto | Hacer clic en cualquier elemento por texto |
fill | > fill Etiqueta valor | Llenar un campo de texto de formulario |
type | > type #selector valor | Escribir en un elemento por selector CSS |
hover | > hover Texto del Elemento | Pasar el cursor sobre un elemento |
select | > select Etiqueta Opción | Seleccionar una opción de un menú desplegable |
scroll | > scroll down 300 | Desplazar hacia abajo en píxeles |
scroll | > scroll up 200 | Desplazar hacia arriba en píxeles |
wait | > wait 2 | Pausar por N segundos |
screenshot | > screenshot nombre.png | Guardar una captura de pantalla |
Selección de Voz
Voces populares de edge-tts (todas gratuitas, no se necesita clave API):
| Voz | Idioma | Estilo |
|---|---|---|
en-US-JennyNeural | Inglés (EE. UU.) | Cálida, conversacional |
en-US-GuyNeural | Inglés (EE. UU.) | Profesional, clara |
en-US-AriaNeural | Inglés (EE. UU.) | Natural, versátil |
en-GB-SoniaNeural | Inglés (Reino Unido) | Pulida, profesional |
it-IT-IsabellaNeural | Italiano | Natural, clara |
de-DE-KatjaNeural | Alemán | Profesional |
fr-FR-DeniseNeural | Francés | Elegante |
es-ES-ElviraNeural | Español | Clara |
ja-JP-NanamiNeural | Japonés | Natural |
zh-CN-XiaoxiaoNeural | Chino | Versátil |
Lista completa: edge-tts --list-voices
Variables
Usa {nombre_variable} en los guiones. Variables integradas:
{base_url}— se establece mediante el argumento--base-url
Variables personalizadas mediante --var clave=valor:
> goto {base_url}/projects/{project_id}
> fill Buscar {search_term}
Salida
La skill produce:
demo_final.mp4— video H.264, audio AAC, optimizado para web (faststart)- Resolución: 1920×1080 (por defecto) o personalizada
- Calidad: CRF 18 (alta calidad), AAC 192kbps
Consejos para Grandes Demos
- Primero el guion — Escribe la narración antes que las acciones. La historia marca el ritmo.
- Escenas cortas — 8-15 segundos por escena. Mantén el ritmo.
- Pausas generosas — Agrega
> wait 1-2después de las navegaciones para dar aire visual. - Empareja narración con acción — Describe lo que ocurre en pantalla mientras ocurre.
- Diapositivas de intro/outro — Úsalas siempre para un acabado profesional.
- Prueba incrementalmente — Graba una escena primero para verificar el tiempo, luego agrega más.
- Consistencia de marca — Los colores de las diapositivas de intro/outro DEBEN coincidir con la paleta de la marca de la PoC (de
threadlight-designPatrón Transversal 1). No uses degradados azules/morados por defecto para un cliente con marca roja. Copia las propiedades CSS personalizadas deldemo-deck.htmlde la PoC en los archivos HTML de la diapositiva. - Subtítulos — Genera un archivo WebVTT a partir del texto de la narración. NO uses
<track src="file.vtt">externo — Edge bloquea CORS en el protocolofile://. En su lugar, incrusta el VTT en línea como una URL de blob de JS:var blob = new Blob([vttData], {type:'text/vtt'}); track.src = URL.createObjectURL(blob);y agrega dinámicamente el elemento<track>. Las marcas de tiempo DEBEN usar el formatoHH:MM:SS.mmm(noMM:SS.mm— Edge lo rechaza). - Incrústalo en el deck — Si la PoC incluye un
demo-deck.html, incrusta el video como respaldo en la tarjeta de demo en vivo. Configura una tecla de alternanciaV: presiona V para reproducir el video en línea en la diapositiva.is-cue, presiona V nuevamente para detenerlo. Agrega una barra de control visible (botón de reproducción/pausa + barra de progreso clickeable + indicador de tiempo) para que el presentador no dependa solo de atajos de teclado. Detención automática en el eventoended. La pista de respaldo ("Presiona V para el respaldo pregrabado") se muestra debajo del texto de la señal en baja opacidad.
Grabación de Demos de Agentes (patrón probado en batalla)
Esta sección se extrajo de 6 intentos fallidos de grabación en una PoC de agente alojado en Foundry. Los patrones a continuación son el único enfoque que produce de manera confiable un video visible cuando el tiempo de respuesta del agente es impredecible (10–50 segundos).
El problema
Las demos de agentes de IA no se pueden grabar en tiempo real. El agente tarda entre 10 y 50 segundos en responder. Si grabas el navegador continuamente y superpones audio de narración pregenerado, la voz describe la respuesta mientras la pantalla aún muestra "Trabajando...". Ninguna cantidad de aceleración posterior o cambio de audio soluciona esto de manera confiable: las dos líneas de tiempo están fundamentalmente desincronizadas.
La solución: cortes de pantalla por escena
Nunca muestres "Trabajando..." en el video. Corta directamente de "pregunta escrita" a "respuesta renderizada". La espera del agente ocurre fuera de cámara entre capturas de pantalla.
Flujo de trabajo por escena:
- Escribe el prompt → captura de pantalla del estado escrito (el narrador presenta la pregunta sobre este fotograma)
- Haz clic en "Preguntar" → consulta hasta que la respuesta se renderice por completo (fuera de cámara — sin grabación)
- Captura de pantalla de la respuesta completa (el narrador describe la respuesta sobre este fotograma)
- Construye segmento: imagen fija + clip de audio de narración correspondiente (duración exacta)
- Concatena todos los segmentos: intro → K1escrito → K1completo → K2escrito → K2completo → … → outro
Espera inteligente — consulta de aparición → desaparición:
# Fase 1: esperar a que el indicador de carga APAREZCA (confirma que la llamada API comenzó)
for _ in range(30):
if await page.evaluate("() => !!document.body.innerText.match(/Working/)"):
break
await page.wait_for_timeout(500)
# Fase 2: esperar a que el indicador de carga DESAPAREZCA (confirma que la respuesta se renderizó)
for _ in range(120):
if not await page.evaluate("() => !!document.body.innerText.match(/Working/)"):
break
await page.wait_for_timeout(1000)
await page.wait_for_timeout(2000) # dejar que el DOM se estabilice
Adapta la expresión regular (/Working/) para que coincida con el indicador de carga que
use el espacio de trabajo. El patrón de 2 fases evita el error común donde el
script verifica antes de que "Trabajando..." siquiera aparezca y continúa inmediatamente.
Construcción de un segmento a partir de una imagen fija + audio:
def make_segment(image_path, audio_path, output_path):
audio_dur = ffprobe_duration(audio_path)
subprocess.run([
"ffmpeg", "-y",
"-loop", "1", "-i", str(image_path),
"-i", str(audio_path),
"-c:v", "libx264", "-preset", "fast", "-crf", "18",
"-c:a", "aac", "-b:a", "192k",
"-t", str(audio_dur),
"-pix_fmt", "yuv420p",
"-movflags", "+faststart", str(output_path),
], check=True)
Cada segmento tiene una duración igual a su audio de narración — el narrador siempre describe lo que está en pantalla.
Anti-patrones (de 6 intentos fallidos de grabación en una PoC de agente alojado en Foundry)
| ❌ Enfoque | Por qué falla |
|---|---|
| Grabar continuamente + superponer audio después | Las líneas de tiempo de audio y video nunca se alinean: el narrador habla sobre citas mientras la pantalla muestra "Trabajando..." |
Acelerar las partes de video de "Trabajando..." con setpts | Se ve entrecortado; el factor de aceleración depende del tiempo de respuesta impredecible del agente |
Temporizadores fijos > wait 35 en el guion | El tiempo de respuesta del agente es de 10 a 50 s; los temporizadores fijos cortan las respuestas o desperdician 30 s mostrando nada |
| Grabar video + audio simultáneamente en tiempo real | Playwright no puede capturar el audio del sistema; Chromium sin interfaz gráfica no tiene dispositivo de audio |
| Postprocesar con detección de cambio de audio | Demasiado frágil; el texto "Trabajando..." aparece en el DOM, pero los indicadores visuales de carga varían según el espacio de trabajo |
Selección de voz para demos de agentes
Usa una voz británica (en-GB-SoniaNeural) para PoCs con audiencia del Reino Unido —
suena natural al ritmo de la demo y coincide con el registro profesional.
Evita las voces casuales de EE. UU. para demos en industrias reguladas (FSI, telco, salud).
Ubicaciones de Archivos
Cuando se activa como una skill global de Copilot CLI, los scripts están en:
~/.copilot/skills/auto-demo-producer/scripts/record_demo.py~/.copilot/skills/auto-demo-producer/scripts/generate_slides.py
Cópialos a tu directorio de proyecto antes de ejecutarlos, o haz referencia directamente.
Prerrequisitos
- Python 3.10+ con
pip - edge-tts —
pip install edge-tts(Microsoft Neural TTS gratuito) - Playwright —
pip install playwright && playwright install chromium - ffmpeg — binario del sistema (ver comandos de instalación arriba)