Video de producto
Construye un video narrado de 60 a 120 segundos que presente un producto usando sus pantallas reales. El resultado es un proyecto HyperFrames (un index.html generado más activos) y un MP4 renderizado.
Escribe cada entrega (guion, texto en pantalla, README) en el idioma de la audiencia. Este archivo está en inglés solo porque son instrucciones.
Estructura de salida
Crea una carpeta por video, fuera de cualquier repositorio de código a menos que el usuario indique lo contrario:
<Product>-video/
ROTEIRO.md | SCRIPT.md guion, tabla de afirmaciones, puntos a confirmar
LEIA-ME.md | README.md qué es real, qué está reconstruido, límites, cómo volver a ejecutar
01-.. 0N-.. activos capturados, una carpeta por fuente
voz/ | voice/ segmentos de narración (texto y audio por escena)
ferramentas/ | tools/ configuraciones y gen.js (el generador de composición)
hyperframes/
index.html GENERADO. Nunca editar a mano.
assets/{img,video,audio,fonts}
renders/
Flujo de trabajo
Ejecuta las fases en orden. Cada una termina con una verificación; no comiences la siguiente fase hasta que la verificación pase.
P1. Fuentes
- Localiza cada fuente que el usuario haya nombrado. Una ruta de otra máquina no existirá: busca el mismo proyecto en las carpetas del usuario actual e indica cuál usaste.
- Clasifica cómo se puede mostrar el producto:
- Aplicación en vivo, accesible: captúrala (P3,
site-capture.cjs,record-interaction.cjs). - Archivo Figma público: captura frames a través de la vista de prototipo (P3,
figma-frames.cjs). No se necesita token. - Detrás de un inicio de sesión sin acceso: pide capturas de pantalla o una cuenta de prueba. No reconstruyas pantallas de memoria.
- Aplicación en vivo, accesible: captúrala (P3,
- Extrae las palabras propias del producto: texto de la página de inicio, nombres de funciones, números, FAQ, términos. Estas son la única fuente permitida para afirmaciones.
Verificación: puedes nombrar la audiencia, los módulos del producto y la fuente de cada hecho que planeas usar.
P2. Guion
Lee references/script.md y escribe el archivo de guion a partir de su plantilla. Las reglas más importantes:
- Presupuesto de 2.3 a 2.6 palabras habladas por segundo. 250 palabras son aproximadamente 100 segundos.
- Una idea por escena, de 8 a 16 segundos por escena, de 6 a 9 escenas.
- Cada afirmación en la narración tiene una fila en la tabla de afirmaciones con su fuente. Omite cualquier cosa que las fuentes no puedan respaldar.
- Escribe para la voz: nombres de marca como se pronuncian, números deletreados, sin abreviaturas que la voz deletrearía letra por letra.
Verificación: la tabla de afirmaciones no tiene celdas de fuente vacías, y la lista de "puntos a confirmar" nombra cada número que provino del texto de marketing.
P3. Activos
Lee references/capture.md para ejemplos de configuración.
| Fuente | Script | Salida |
|---|---|---|
| Aplicación web en vivo, estática | scripts/site-capture.cjs | pliegue inicial, página completa, capturas de paso, videos de desplazamiento, recortes |
| Aplicación web en vivo, flujos | scripts/record-interaction.cjs | clips de interacción con cursor o superposición táctil |
| Archivo Figma público | scripts/figma-frames.cjs | un PNG por frame, recortado al frame |
También recopila la marca: logotipo (vector si existe), los archivos de fuente de la marca con su licencia, y los tokens de color del CSS del producto. Lee los estilos que usan las páginas del producto con scripts/page-styles.cjs <url>: familia de titulares, peso, altura de línea y espaciado entre letras, estilos de botones y cualquier superficie de vidrio esmerilado. El video los copia en lugar de adivinarlos.
Verificación: abre algunas capturas y míralas. Una captura que muestre una pantalla de inicio de sesión, un banner de cookies o una superposición de desarrollo es una captura fallida.
P4. Voz
Lee references/voice.md. Pregunta qué voz tiene el usuario antes de generar nada: un servicio pago accesible mediante MCP o una clave API es lo primero, una narración suministrada es lo segundo. Un modelo local gratuito es solo para un usuario que lo solicite, porque instala un modelo en su máquina.
- Servicio de voz mediante MCP: genera toda la narración como una sola toma continua (un párrafo por escena, una etiqueta de entrega al inicio). Alínea con
scripts/voice.py --existing, corta en las pausas conscripts/split-take.py --level, luego une los archivos de escena conscripts/voice.py --parts "voz/cena-{id}.wav". Los límites de las escenas son exactos y el tono se mantiene igual de la primera a la última escena. Una narración solicitada escena por escena cambia el estado de ánimo entre solicitudes. - Servicio de voz mediante una clave API:
scripts/voice.py --provider elevenlabs --el-voice <id>genera y une.scripts/elevenlabs.pyverifica la conexión, clasifica voces y compone música. - Narración suministrada: pasa
--existing. Los límites de las escenas provienen de alinear la transcripción con el guion.
Con un modelo expresivo, configura la entrega con una [etiqueta de audio] al inicio de la toma. Cada escena lleva text (limpio, para subtítulos) y puede llevar tts (lo que recibe la voz, cuando difiere).
En todos los modos, las marcas de tiempo de las palabras están alineadas con el texto del guion, por lo que los subtítulos nunca muestran un error de transcripción. Lee la lista misheard que imprime: cualquier cosa que no sean números deletreados y homófonos es un problema de pronunciación. Corrige el texto del guion y regenera.
Normaliza la narración a aproximadamente −18 LUFS antes de componer.
Verificación: voiceover.json existe, la duración total está dentro del 10% del objetivo, misheard está explicado, y scripts/voice-tone.py --scenes reporta una dispersión de la mediana del tono entre escenas de aproximadamente 3 semitonos o menos.
P5. Composición
Lee references/hyperframes.md (las reglas que aplica el renderizador) y comienza desde assets/gen-template.js.
- Genera
index.htmldesde un script. Los cambios de tiempo ocurren cada vez que cambia la voz; un generador absorbe eso, las ediciones manuales no. - Ancla cada animación a una frase de la narración (
at(3, 'No painel')), nunca a una sola palabra corta. "no", "e" y "um" aparecen varias veces por escena y la primera coincidencia es la incorrecta. - Reserva el 17% inferior del marco para subtítulos. Nada más entra en esa banda.
- Muestra pantallas reales dentro de una ventana de navegador o maqueta de dispositivo. Coloca la explicación al lado, no encima.
- Prefiere un resaltado claro por oración (un círculo, un zoom, un movimiento del cursor) sobre muchos pequeños.
- Los titulares toman el estilo de titular propio del producto y las etiquetas toman su lenguaje de superficie, ambos leídos en P3. No uses por defecto el peso más pesado.
- Para historias, reels o shorts, lee
references/vertical.mdy construye una segunda composición vertical a partir de la misma narración, comenzando desdeassets/gen-vertical-template.js. Nunca recortes la composición 16:9.
Verificación: npx hyperframes lint tiene 0 errores.
P6. Verificar
npx hyperframes checkdebe terminar con "Check passed" (lint, tiempo de ejecución, diseño, movimiento, contraste).npx hyperframes snapshot --no-end --at <un tiempo por escena, más cada resaltado>y mira cada frame. Construye hojas de revisión 2×2 con ffmpeg para revisar más rápido.- Compara cada frame con lo que dice la narración en ese segundo. Los defectos habituales: pantalla incorrecta para la oración, un resaltado en el elemento equivocado, texto que se ajusta mal, un elemento dentro de la banda de subtítulos.
- Renderiza un borrador (
render -q draft), luego verifica el MP4 en sí:ffprobepara duración y flujos,loudnormpara sonoridad (objetivo −16 a −17 LUFS con música), y frames extraídos con ffmpeg.
Verificación: has mirado un frame de cada escena tomado del MP4, no solo de las instantáneas.
P7. Entregar
Escribe el README con: qué es real (capturado), qué se reconstruyó en HTML con datos reales, qué es conceptual, límites conocidos, los comandos para previsualizar, verificar y renderizar, y cómo cambiar la voz. Luego informa al usuario: qué se hizo, qué se verificó y qué aún necesita una decisión humana (números no confirmados, música, calidad de voz).
Errores ya pagados
| Código | Síntoma | Causa y solución |
|---|---|---|
| X1 | Las pantallas cambian un segundo antes | at() coincidió con el primer "no" o "e". Ancla en frases. |
| X2 | Un elemento permanece oculto durante escenas enteras | Dos interpolaciones fromTo en el mismo elemento; la posterior renderiza su estado "from" inmediatamente. Usa un elemento por aparición, o to() desde un estado inicial CSS. |
| X3 | El sitio responde 403 al script pero se abre en un navegador | Agente de usuario headless. Usa lib/browser.cjs, que envía un UA de escritorio. |
| X4 | "El ejecutable no existe" al iniciar | La compilación del navegador instalada difiere de la versión de Playwright. lib/browser.cjs recurre al Chromium local más nuevo, luego a Chrome. |
| X5 | La captura de página completa se corta en un pliegue | La aplicación desplaza un contenedor interno. Encuentra el elemento desplazable más grande y aumenta el viewport a su altura. |
| X6 | La grabación de desplazamiento se entrecorta | La tasa de fotogramas del screencast es variable. Renderiza los desplazamientos fotograma a fotograma. |
| X7 | Revisas un archivo que nunca cambia | El grabador escribe en una carpeta diferente a la que inspeccionas. Imprime y verifica la ruta de salida. |
| X8 | Un contador se renderiza diminuto junto a un "%" enorme | Un selector descendente (.num span) también coincidió con el span del contador interno. Usa selectores de hijo para las etiquetas. |
| X9 | Los subtítulos muestran una palabra incorrecta | Los subtítulos provinieron de la transcripción bruta. Alinea los tiempos con el texto del guion (voice.py hace esto). |
| X10 | La voz pronuncia mal la marca o un término | Escríbelo como se habla (una marca escrita como una palabra se narra como dos, un término extranjero recibe una frase nativa), deletrea los números, expande las abreviaturas. |
| X11 | Una segunda ejecución de captura borró el índice de la primera | Fusiona los archivos de índice entre ejecuciones en lugar de sobrescribir. |
| X12 | El video dentro de un contenedor con tiempo falla la verificación | El medio temporizado lleva class="clip" él mismo; su contenedor no tiene tiempo. |
| X13 | La captura del prototipo incluye un toast o barra de cookies | Cierra y oculta las superposiciones antes de la captura de pantalla, luego recorta al frame. |
| X14 | La grabación muestra botones solo de prototipo | Oculta los controles de prueba y desarrollo por selector o prefijo de texto antes de grabar. |
| X15 | Afirmaciones que el producto no puede probar | "Primero", "total", "garantizado" necesitan una fuente. Déjalas fuera o muévelas a "puntos a confirmar". |
| X16 | Un número de marketing no tiene base | Verifica de dónde vino antes de usarlo: busca en los documentos y en el historial de git de la página (git log -S'<número>'). Un número añadido a mano en una edición de texto no es evidencia. Deséchalo. |
| X17 | El corte vertical es ilegible | Una pantalla de escritorio en 9:16 tiene texto de 9 px, y un recorte todavía parece de escritorio. Muestra un elemento adaptado a la vez en un panel, como lo hace la página de inicio móvil del producto (references/vertical.md). |
| X18 | La narración suena dramática o eufórica | Las etiquetas no verbales ([suspira]), [emocionado] y [serio] se exceden en un video de producto. Usa [calmado] y [cálido], regenera solo las escenas nombradas y compara tomas con scripts/voice-tone.py. |
| X19 | El diseño parece una página web | Columna alineada a la izquierda, etiquetas de sección sobre titulares, un logotipo pequeño en una esquina. En video vertical: centra todo, quita las etiquetas, haz el logotipo más grande y centrado. |
| X20 | El eslogan está lejos del logotipo | La exportación del logotipo tiene relleno transparente. Recorta el archivo y posiciona contra la marca real. |
| X21 | La narración es plana en algunas escenas y emocionada en otras | Cada escena fue una solicitud separada con su propia etiqueta, por lo que cada una fue una interpretación separada. Genera una sola toma continua con una etiqueta, córtala en las pausas con scripts/split-take.py y mide con scripts/voice-tone.py --scenes. Una dispersión de 5 semitonos entre escenas se percibió como cambios de humor, 2 como uniforme. |
| X22 | Los titulares se ven pesados y diferentes al producto | Se asumió el peso (800). Lee el estilo de titular propio del producto con scripts/page-styles.cjs y copia familia, peso, altura de línea y espaciado entre letras. |
| X23 | Las palabras se juntan en un titular | El espaciado ajustado entre letras copiado de una página web cierra los espacios entre palabras en tamaños de video. Agrega word-spacing: .07em. |
| X24 | Una etiqueta de vidrio parece blanca sólida, o su desenfoque aparece después del fundido | El fondo es demasiado opaco (mantén la parte inferior cerca de 0.6), o el fundido está en un padre: la opacidad por debajo de 1 en un ancestro corta el elemento de lo que está detrás. Anima el elemento que tiene backdrop-filter. |
| X25 | La verificación de contraste falla en texto que se ve bien | La verificación muestreó un frame en medio de un fundido. Toma una instantánea en el momento reportado. Si el elemento está a medio entrar, mueve la entrada unos frames y vuelve a ejecutar la verificación. Las composiciones muy cortas sufren más esto. |
Archivos en esta skill
references/script.md: plantilla de guion, ritmo, tabla de afirmaciones, tabla de pronunciación.references/capture.md: configuraciones para los tres scripts de captura, especificaciones de captura, activos de marca.references/voice.md: configuración de TTS, voces, alineación, sonoridad, música, intercambio de narración.references/hyperframes.md: reglas de composición, comandos CLI, zonas de diseño.references/vertical.md: versión 9:16 para historias: área segura, cámara en la pantalla, subtítulos, división en partes.assets/gen-template.js: generador de composición 16:9 para copiar en la carpeta de herramientas del proyecto.assets/gen-vertical-template.js: generador vertical con una edición completa y una corta.scripts/lib/browser.cjs,scripts/site-capture.cjs,scripts/record-interaction.cjs,scripts/figma-frames.cjs,scripts/element-shots.cjs,scripts/page-styles.cjs,scripts/voice.py,scripts/split-take.py,scripts/voice-tone.py,scripts/elevenlabs.py,scripts/lib/eleven.py.
El código de la API de ElevenLabs (--provider elevenlabs, elevenlabs.py) fue escrito sin una clave para probar. Su primera ejecución real puede necesitar una corrección; la ruta --parts y la ruta local están probadas.