Communitygithub.com

timscheuerai/content-vault

Crea un vídeo de lanzamiento con gráficos animados de 30 a 60 segundos para un producto o función de <TU_MARCA>. Composición React con Remotion 4 + narración AI de ElevenLabs + efectos de sonido + música de fondo, sincronización basada en ritmos, sistema de diseño alineado con la marca.

¿Qué es content-vault?

Este skill construye automáticamente un vídeo de lanzamiento de gráficos animados (motion graphics) de 30 a 60 segundos para un producto o funcionalidad de tu marca, utilizando Remotion 4 para la composición en React, ElevenLabs para la narración y efectos de sonido, y una sincronización precisa con la música de fondo. Está diseñado para responder a comandos como "crea un vídeo de lanzamiento", "haz un vídeo de producto", "vídeo para la función X" o "/launch-video". El skill organiza todo el flujo de trabajo: desde la definición de un guion por fases, la generación de audio (narración, SFX y música) con caché hash para ahorrar tiempo, hasta la composición visual con escenas modulares (fondo hero, cursor, tablas de datos, paneles, confeti, etc.). Es ideal para equipos de producto, marketing o ingeniería que necesiten producir vídeos promocionales de alta calidad de forma repetible, con un sistema de diseño personalizable (colores, tipografía, modos visuales). No debe usarse para gráficos estáticos, presentaciones, clips cortos ni grabaciones de pantalla reales; para esos casos existen otros skills específicos.

Compatible con✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/timscheuerai/content-vault/tree/HEAD/skills/launch-video

Preguntar en tu IA favorita

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

Documentación

Creador de vídeos de lanzamiento

Construye un vídeo de lanzamiento con gráficos animados de 30 a 60 segundos para un producto o función de <TU_MARCA>, de principio a fin:

  • Composición React con Remotion 4 renderizada a MP4 (1920×1080 + 1080×1080)
  • Narración AI de ElevenLabs (voz Bill por defecto), efectos de sonido por evento y una pista de música de fondo
  • Sincronización basada en ritmos: cada fase visual lee su fotograma de inicio a partir de las duraciones de audio medidas en script.timings.json. Edita el guion → regenera el audio → todos los elementos visuales se ajustan automáticamente. Sin ajustes manuales de fotogramas.
  • Si tu marca tiene un subsistema de movimiento (componentes de cristal/cursor/píldoras de herramientas), hereda de ahí. Los patrones de referencia descritos a continuación son un sistema válido: un subsistema de movimiento de cristal esmerilado (shells de chat, cursor, píldoras de herramientas) superpuesto sobre un sistema tabular blanco limpio (tablas de resultados, paneles, trazas).

Si tu repositorio tiene un proyecto de referencia de Remotion, apunta este skill hacia él. De lo contrario, los patrones descritos aquí son autónomos. Ruta de implementación de referencia en el repositorio fuente: <TU_RUTA_DE_VIDEO_DE_REFERENCIA>.


Cuándo usarlo

Actívalo con:

  • "Crea un vídeo de lanzamiento para X"
  • "Haz un vídeo de lanzamiento / vídeo de producto / revelación de funcionalidad"
  • "Renderiza un vídeo para la [funcionalidad]"
  • El usuario escribe explícitamente /launch-video

No lo uses para:

  • Gráficos estáticos para redes sociales → /graphics-designer
  • Presentaciones de diapositivas / webinars → el pipeline de presentaciones
  • Clips publicitarios cortos < 8s → normalmente basta con un still de Remotion o una composición de una sola escena; el pipeline completo de este skill es excesivo.
  • Grabaciones de vídeo sin editar (cabezas parlantes, grabaciones de webinars, vídeos de fundadores, entrevistas con clientes, demos con captura de pantalla) → usa /video-use en su lugar. Ese skill corta en límites de palabra a partir de una transcripción de Scribe, elimina palabras de relleno, corrige el color y quema subtítulos. Este skill es para gráficos animados sintéticos construidos desde cero en Remotion. Ambos se complementan: una edición de /video-use puede generar espacios de superposición de Remotion para insertar animaciones de marca, pero el montaje proviene de /video-use.

Arquitectura en un diagrama

motion/<nombre-del-video>/
├── package.json              # remotion 4 + react 19 + tsx + dotenv + mp3-duration
├── remotion.config.ts        # publicDir → ../../brand/motion (única fuente de assets)
├── tsconfig.json
├── SCRIPT.md                 # guion de narración legible por humanos (por ritmo)
├── .env                      # ELEVENLABS_API_KEY (¡gitignored!)
├── .env.example
├── generate-audio.ts         # ejecutor de narración de ElevenLabs, cacheado por hash por ritmo
├── generate-sfx.ts           # ejecutor de generación de sonido de ElevenLabs, cacheado por hash
├── generate-music.ts         # ejecutor de música de ElevenLabs + recorte de silencio inicial
├── script.timings.json       # duraciones de narración (generado)
├── sfx.timings.json          # duraciones de SFX (generado)
├── music.timings.json        # duración de música (generado)
└── src/
    ├── Root.tsx              # registerRoot
    ├── Video.tsx             # registro de composición + envoltorio LaunchVideoComposition
    ├── theme.ts              # fps + duración + colores (refleja <TU_RUTA_DE_TOKENS_DE_MARCA>)
    ├── script.ts             # ritmos de narración (id, fase, texto)
    ├── timings.ts            # cargador de script.timings.json + beatStartFrame()
    ├── sfx.ts                # definiciones de clips SFX (anclados a fotogramas)
    ├── music.ts              # prompt de música + volumen
    ├── Narration.tsx         # pista de secuencia solo de narración
    ├── SoundDesign.tsx       # narración + SFX + música combinados
    └── scenes/
        ├── HeroBackground.tsx      # /video/hero-bg.mp4 en bucle
        ├── OpeningScene.tsx        # escena de orquestación (ancla todas las fases)
        ├── GlassCursor.tsx         # cursor "tú" estilo multijugador
        ├── CompanyTable.tsx        # tabla de datos con revelación de columnas
        ├── AgentDashboard.tsx      # vista semanal de Google Calendar
        ├── AgentRunDetail.tsx      # vista de traza de llamada a herramienta
        ├── MemoryPanel.tsx         # panel de estadísticas + gráfico de chispa
        ├── Confetti.tsx            # explosión de partículas
        └── ClosingCard.tsx         # callback de chat de cierre (el patrón "Invitando")

Los assets viven en brand/motion/:

  • video/hero-bg.mp4 + póster (bucle de fondo hero de tu marca · ej. un vídeo ambiental en brand/motion/video/hero-bg.mp4)
  • logos/{models,tools,companies,sequencers}/ — marcas de terceros
  • audio/{launch-narration,sfx,music}/ — mp3 generados (commiteados para renders reproducibles)
  • components/HeroChatMockup.tsx — shell de chat independiente del framework

Flujo de trabajo para un nuevo vídeo de lanzamiento

1. Brief

Obtén del usuario:

  • Audiencia: ¿para quién es? (equipos de GTM? Ingenieros? Inversores?)
  • Duración: tiempo objetivo en segundos (por defecto 30-45s; 60s+ se siente largo para hype)
  • Mensajes clave: 4-8 cosas a comunicar, en orden narrativo
  • Formatos de salida: apaisado (web/LinkedIn), cuadrado (IG/feed) o ambos

2. Esbozar ritmos

Cada ritmo = una frase de narración que cae durante una fase visual. Normalmente 6-8 ritmos. La suma de las longitudes de audio de los ritmos = duración total. Los ritmos deberían durar 3-7s cada uno.

Para cada ritmo captura: id, phase (descripción visual en una línea), text (línea hablada, de 10 a 20 palabras).

3. Escribir SCRIPT.md

Guarda el guion como un hermano de package.json para revisión humana. Formato:

## Ritmo N — Nombre de la fase
**Fotogramas** ~inicio–fin (segundos) · **objetivo ~Npalabras**

> "Línea hablada aquí."

**Sincronización visual:** qué ocurre en pantalla.

4. Construir src/script.ts

Refleja SCRIPT.md como datos. El generador de narración y la composición importan SCRIPT. Sin imports de Remotion aquí para que los generadores puedan ejecutarse en Node normal:

export interface Beat { id: string; phase: string; text: string; }
export const SCRIPT: Beat[] = [...];
export const AUDIO_SUBDIR = "audio/launch-narration";
export function audioPath(id: string) { return `${AUDIO_SUBDIR}/${id}.mp3`; }

5. Generar narración

cd motion/<nombre-del-video>
cp .env.example .env  # pega ELEVENLABS_API_KEY
npm install
npm run generate-audio

Esto crea brand/motion/audio/launch-narration/{beat-id}.mp3 y escribe las duraciones en script.timings.json. Hashea por texto del ritmo, de modo que los ritmos sin cambios se omiten en ejecuciones posteriores (iteración económica).

6. Construir la escena visual

En OpeningScene.tsx:

  1. Calcula los inicios de los ritmos al cargar el módulo:
    const HERO_BEAT     = beatStart("hero", 0);        // → 0
    const DATABASE_BEAT = beatStart("database", 0);    // → 171 (después de que hero termine)
    // ... etc
    
  2. Expresa cada fotograma de animación como BEAT_X + offset:
    const BADGE_IN     = HERO_BEAT + 6;
    const TYPE_START   = HERO_BEAT + 38;
    const TOOLS_START  = HERO_BEAT + 115;  // sincronizado con la letra "GTM stack"
    const CURSOR_PRESS = HERO_BEAT + 165;
    
  3. Funde entre escenas de fase usando puertas de opacidad por ritmo.

7. Generar SFX (opcional pero de alto impacto)

Define los momentos de clic/transición en src/sfx.ts. Ancla cada clip a un fromFrame específico usando el mismo ayudante beatStartFrame(). Ejemplos de clips que merecen un lugar:

  • textura de escritura bajo la animación del prompt
  • clic nítido en las pulsaciones del cursor
  • pop de celebración en momentos de "inscripción" / finalización
  • sutil crescendo en la revelación de la tarjeta de cierre
npm run generate-sfx

8. Generar música

Define un prompt + duración en src/music.ts. generate-music.ts recorta automáticamente el silencio inicial (la música de ElevenLabs suele abrir con un compás en silencio que se lee como "sin música" contra la narración).

npm run generate-music

9. Iterar con renders

npm run render:landscape

Renderizar toma ~30-90s. Siempre recodifica la salida a rango TV yuv420p para compatibilidad con QuickTime — el vídeo de fondo es yuvj420p (rango JPEG) y la propagación rompe la reproducción en algunos reproductores:

ffmpeg -y -i out/launch-landscape.mp4 \
  -c:v libx264 -profile:v high -level:v 4.0 \
  -pix_fmt yuv420p -color_range tv -crf 18 -c:a copy \
  out/launch-landscape-fixed.mp4
mv out/launch-landscape-fixed.mp4 out/launch-landscape.mp4

Usa ffmpeg -ss N -i ... -frames:v 1 /tmp/check.jpg para verificar marcas de tiempo específicas sin ver el render completo.


Reglas de diseño

Voz (visual + hablada)

  • Nunca uses guiones largos. Solo puntos, comas, dos puntos, paréntesis, punto medio.
  • Palabras prohibidas en cualquier lugar: apalancar, sinergia, robusto, de clase mundial, sin fisuras, intuitivo, potente, innovador.
  • Los números vencen a los adjetivos ("8 herramientas" no "muchas herramientas").
  • Conciso, concreto. Sin rodeos.
  • Cierre: liderado por la marca, no "Felicidades." El patrón de cierre más fuerte encontrado aquí: remate "Invitando" → entrada de chat con un nuevo prompt escrito → firma URL. El callback del chat a la apertura vence a la celebración cada vez.

Color (ejemplo de tokens · ajústalo a tu marca)

Claro, neutro. Solo un acento, usado una vez por escena donde tenga significado (punto vivo, resaltado, estado de éxito).

TokenHexUso
--bg#fafafafondo de página
--surface#fffffftarjetas, paneles
--ink#0a0a0atexto principal + números
--muted#71717atexto secundario
--line#e4e4e7bordes
--accent#10b981el único acento

Tipografía

  • Pila: 'Helvetica Neue', Helvetica, Arial, sans-serif
  • Mono (kickers, código, etiquetas): ui-monospace, 'SFMono-Regular', Menlo
  • Tipografía hero: peso 450 con tracking ajustado (-0.05em)
  • Estilo kicker mono: 11-14px, mayúsculas, interletraje 0.16-0.18em, color #71717a o #a1a1aa
  • Las partes en negrita/media en el cuerpo de texto gris apagado reflejan el patrón de la marca: <span style={{ color: "#0a0a0a", fontWeight: 500 }}>negrita</span> vs el texto circundante #71717a.

Dos modos visuales

Elige uno por escena; no los mezcles:

  1. Vidrio esmerilado / en el producto — shell de chat, cursor, píldoras de herramientas, sobre el vídeo de fondo hero. Vidrio blanco con backdrop-filter: blur(28px), rgba(255,255,255,0.45).
  2. Blanco limpio / tabular — tablas, paneles, trazas, panel de memoria. bg #ffffff, 1px solid #e4e4e7, sombra sutil.

La transición de fundido de fondo entre modos es uno de los momentos más cinematográficos; reserva ~20-30 fotogramas y usa Easing.bezier(0.4, 0, 0.2, 1) (estándar de material) para suavidad.


Reglas de animación

  1. Amortiguación 22-28 en muelles. Por debajo de 20 obtienes rebote que se lee como amateur. Usa 14-18 solo cuando quieras intencionadamente un "pop".
  2. Escalonados más ajustados > más lentos. El primer instinto es siempre ralentizar; la segunda pasada suele implicar reducir los escalonados a la mitad. Escalonado por defecto entre elementos en cascada: 3-6 fotogramas.
  3. Sincroniza los elementos visuales con la letra donde importe. Si la narración dice "GTM stack", las píldoras de herramientas deben aparecer en esa palabra — no 3s antes. Usa with_timestamps de ElevenLabs para sincronización a nivel de palabra, o estima a partir de la duración del ritmo / recuento de palabras si lo aproximado está bien.
  4. Reserva alturas de fila. Cuando tablas/tarjetas animan texto, minHeight en la fila evita que el diseño salte mientras se llena el contenido. Se ve mal si las filas crecen durante la cascada.
  5. Renderiza condicionalmente en lugar de opacidad 0 si crearía un rectángulo vacío alto. Las tarjetas que aún no han comenzado a revelarse no deberían ocupar espacio.
  6. Funde entre modos de escena, no hagas cortes bruscos. Cada escena principal obtiene una puerta de opacity animada mediante interpolate + curvas de ease.

Problemas comunes de ElevenLabs

  • Voz + modelo por defecto: generate-audio.ts usa por defecto Bill (pqHfZKP75CvOlQylNhV4) en eleven_multilingual_v2. Bill es la voz de caso de uso advertisement en la biblioteca de ElevenLabs: sabia, madura, nítida. Suena como una locución publicitaria real, no como "chico AI en redes sociales". multilingual_v2 es el modelo más estable + realista para narración de producción. No uses eleven_turbo_v2_5 para vídeos de lanzamiento — es el modelo rápido/barato y la diferencia es audible contra un vídeo de fondo hero. Turbo está bien para previsualizaciones / comprobaciones de sincronización de SFX, no para el render final.
  • Ajustes de voz integrados en el script: stability 0.40, similarity_boost 0.75, style 0.30, use_speaker_boost true. Según las mejores prácticas de ElevenLabs: estabilidad por debajo de 0.30 es inestable, por encima de 0.60 es monótono; similitud 0.75 es el punto óptimo de la documentación; estilo 0.20–0.40 añade expresividad sin desviación. No empujes el estilo por encima de 0.4 a menos que quieras oscilaciones de entonación notables.
  • La clave de caché de voz incluye voz + modelo + ajustes. Cambiar cualquiera de esos (o editar el texto del ritmo) invalida el MP3 en caché y vuelve a renderizar el ritmo. Simplemente edita .env (VOICE_ID=... MODEL_ID=...) o generate-audio.ts y vuelve a ejecutar npm run generate-audio.
  • Otras voces de calidad de narración si Bill no encaja:
    • Eric cjVigY5qzO86Huf0OWal — suave, confiable, sensación moderna de SaaS
    • Chuck Miller HIGUfNOdjuWQwwapnTRW — clon profesional, áspero grave, cinematográfico
    • George JBFqnCBsd6RMkjVDRZzb — narrador británico, narrative_story
    • Logan jD4PjnscE4XmlzgsuqY0 — clon profesional, narrador joven
    • Brian nPczCjzI2devNBz1zQrb — el predeterminado heredado; etiquetado social_media, suena más a "AI" que Bill
    • Prueba A/B estas muestras en tu proyecto de referencia de Remotion antes de comprometerte
  • El listado de voces requiere permiso voices_read. Algunas claves no lo tienen; si no puedes hacer GET /v1/voices, recurre a IDs conocidos.
  • La API de Música rechaza nombres de marca en prompts. "Apple keynote", "Linear launch trailer" etc. desencadenan una violación de los TOS. Describe la vibra sin nombrar marcas ("instrumental cinematográfico para un tráiler de lanzamiento de tecnología moderna", "ritmo electrónico pulsante con melodía de sintetizador arpegiado").
  • La música comienza con silencio inicial (~1-2s) por defecto. El pase silenceremove de ffmpeg del generador lo elimina para que la reproducción comience en el fotograma 0. Mantén ese filtro en su lugar.
  • La duración mínima de los efectos de sonido es de 0.5s. Cualquier valor inferior provoca un error en la API. Redondea hacia arriba.
  • Volumen de la música: 0.10 se lee como silencioso bajo la narración; 0.15-0.18 es el punto óptimo — claramente presente pero no lucha contra la voz.

Trampas a evitar

  1. Añadir <Audio> sin <Sequence>: se reproducirá continuamente a través de los límites de la escena. Envuelve siempre cada pista de audio en un <Sequence from={...} durationInFrames={...}> para que su duración coincida exactamente con su ubicación en la línea de tiempo.
  2. Usar elementos HTML anidados absolutos para el diseño: Remotion usa <div> con posicionamiento absoluto para la animación; el diseño anidado se comporta de forma diferente que en la web. Prefiere el posicionamiento absoluto plano sobre los contenedores. Si necesitas grupo, usa <Group> de remotion o un <div> simple sin posicionamiento.
  3. Olvidar publicDir: si tu vídeo de fondo no aparece en el render, comprueba remotion.config.ts. La propiedad publicDir debe señalar el directorio compartido de assets (ej. ../../brand/motion). No copies assets en la carpeta public/ del proyecto, ya que se ignoran a favor de publicDir.
  4. Dependencia de process.env en tiempo de render: Remotion empaqueta con webpack; las variables de entorno deben pasarse a través de bundle u obtenerse desde un archivo .env cargado con dotenv antes de importar @remotion/renderer. generate-audio.ts usa dotenv en la raíz; las composiciones de render deberían leer los timings de script.timings.json en lugar de .env directamente.
  5. Saltarse el pase ffmpeg yuv420p: el vídeo de fondo (yuvj420p) propaga su espacio de color a la composición completa. Sin -pix_fmt yuv420p -color_range tv, el MP4 resultante aparece como un rectángulo verde en QuickTime y la mayoría de los visores de macOS. Siempre haz este paso.
  6. No hacer coincidir la duración de la música con la narración: la música de ElevenLabs se genera con una duración fija. Si no recortas la música para que coincida con la duración total de la narración (mediante generate-music.ts), se cortará en medio de un compás o continuará en silencio. El generador gestiona esto automáticamente.
  7. Usar la API de Voces sin permisos: muchas claves de API de ElevenLabs no tienen voices_read. El listado de voces falla con 403. Mantén una lista de IDs de voz conocidos como respaldo. El script genera un error controlado si el listado falla y sugiere usar IDs predefinidos.
  8. UI de chat con altura fija: el shell de chat (HeroChatMockup.tsx) debe crecer dinámicamente a medida que se escriben los mensajes. Si está en altura fija, el texto se desborda. Establece minHeight o deja que los mensajes empujen el shell hacia abajo con transiciones de altura animadas.
  9. Subir el volumen de los SFX por encima de la narración: los efectos de sonido deberían estar a -12dB a -18dB en relación con el pico de la narración. El volumen de la narración en ElevenLabs está normalizado; asume el pico de la narración como -2dBFS y ajusta los SFX en consecuencia. Demasiado fuerte distrae; demasiado bajo, nadie los nota.
  10. Olvidar los puntos de interrupción responsive: los renders apaisados (1920×1080) y cuadrados (1080×1080) usan el mismo guion pero diferente tamaño de bastidor. Escena que dependen de la anchura (como tablas de datos con columnas) necesitan consultas de medios o porcentajes para escalar. No asumas que todos los renders son apaisados.

Compartición de audio y diseño modular

No dupliques el diseño. Los assets de audio (narración, SFX, música) se escriben en brand/motion/audio/ — el directorio compartido de assets en la raíz del monorepo. Cualquier vídeo puede importar pistas de audio de otros vídeos importando su metadata de timings y construyendo rutas staticFile() que señalen los directorios compartidos. Esto significa que un vídeo sobre la "Función X" puede reutilizar la música de fondo genérica de la marca desde brand/motion/audio/music/marca-generica.mp3 sin copiar archivos.

Consejo de organización de escenas: mantén cada escena en su propio archivo (OpeningScene.tsx, CompanyTable.tsx, etc.). La escena de orquestación (OpeningScene) gestiona la línea de tiempo y pasa fotogramas de inicio como props. Si una escena necesita datos compartidos (ej. lista de herramientas de script.ts), impórtalos directamente — no los aplanes a través del árbol de componentes.

Patrón de composición reutilizable: cualquier escena que pueda aparecer en varios vídeos (ej. GlassCursor.tsx, Confetti.tsx) debería exportar un componente que acepte fromFrame + durationInFrames. La orquestación del vídeo padre simplemente sin duplicar la lógica de animación.

Skills relacionados