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-useen 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-usepuede 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 enbrand/motion/video/hero-bg.mp4)logos/{models,tools,companies,sequencers}/— marcas de tercerosaudio/{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:
- 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 - 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; - 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).
| Token | Hex | Uso |
|---|---|---|
--bg | #fafafa | fondo de página |
--surface | #ffffff | tarjetas, paneles |
--ink | #0a0a0a | texto principal + números |
--muted | #71717a | texto secundario |
--line | #e4e4e7 | bordes |
--accent | #10b981 | el ú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#71717ao#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:
- 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). - 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
- 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".
- 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.
- 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_timestampsde 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. - Reserva alturas de fila. Cuando tablas/tarjetas animan texto,
minHeighten la fila evita que el diseño salte mientras se llena el contenido. Se ve mal si las filas crecen durante la cascada. - 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.
- Funde entre modos de escena, no hagas cortes bruscos. Cada escena principal obtiene una puerta de
opacityanimada medianteinterpolate+ curvas de ease.
Problemas comunes de ElevenLabs
- Voz + modelo por defecto:
generate-audio.tsusa por defecto Bill (pqHfZKP75CvOlQylNhV4) eneleven_multilingual_v2. Bill es la voz de caso de usoadvertisementen la biblioteca de ElevenLabs: sabia, madura, nítida. Suena como una locución publicitaria real, no como "chico AI en redes sociales".multilingual_v2es el modelo más estable + realista para narración de producción. No useseleven_turbo_v2_5para 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=...) ogenerate-audio.tsy vuelve a ejecutarnpm 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; etiquetadosocial_media, suena más a "AI" que Bill - Prueba A/B estas muestras en tu proyecto de referencia de Remotion antes de comprometerte
- Eric
- El listado de voces requiere permiso
voices_read. Algunas claves no lo tienen; si no puedes hacerGET /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
silenceremovede 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.10se lee como silencioso bajo la narración;0.15-0.18es el punto óptimo — claramente presente pero no lucha contra la voz.
Trampas a evitar
- 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. - 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>deremotiono un<div>simple sin posicionamiento. - Olvidar
publicDir: si tu vídeo de fondo no aparece en el render, compruebaremotion.config.ts. La propiedadpublicDirdebe señalar el directorio compartido de assets (ej.../../brand/motion). No copies assets en la carpetapublic/del proyecto, ya que se ignoran a favor depublicDir. - Dependencia de
process.enven tiempo de render: Remotion empaqueta con webpack; las variables de entorno deben pasarse a través debundleu obtenerse desde un archivo.envcargado condotenvantes de importar@remotion/renderer.generate-audio.tsusadotenven la raíz; las composiciones de render deberían leer los timings descript.timings.jsonen lugar de.envdirectamente. - 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. - 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. - 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. - 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. EstableceminHeighto deja que los mensajes empujen el shell hacia abajo con transiciones de altura animadas. - 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.
- 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.