Video de Presentación
Convierte una presentación o un esquema de diapositivas en un video animado narrado que avanza automáticamente. Cada diapositiva se reconstruye como gráficos en movimiento — revelaciones escalonadas de elementos, transiciones reales, sincronización bloqueada con la locución — no es una grabación de pantalla de alguien haciendo clic en PowerPoint.
Cuándo usarlo
- Un pitch deck, seminario web o módulo de curso que debe convertirse en un video que se reproduce solo.
- Un esquema con viñetas que necesita convertirse en diapositivas animadas y narradas.
- Una presentación donde el tiempo de cada diapositiva debe coincidir exactamente con la locución (avance automático, sin clics).
Reconstruir, no grabar
Una grabación de pantalla hereda el aspecto estático de la presentación, el temblor del ratón y los cortes abruptos entre diapositivas. Reconstruir en código (Remotion) ofrece: revelaciones deterministas fotograma a fotograma, transiciones que realmente suavizan el movimiento, texto que se mantiene nítido a cualquier resolución y duraciones de diapositiva determinadas por la longitud del audio. La presentación se convierte en el guion; el video es un nuevo artefacto.
Flujo narrativo: la presentación es un argumento, no N diapositivas
Antes del tiempo o el movimiento, arregla la historia. Un video de presentación que avanza solo no tiene presentador que retome un hilo perdido — la estructura debe sostener la lógica por sí misma. Construye la columna vertebral primero; las diapositivas son los puntos de apoyo.
- Un solo hilo conductor (la columna vertebral). Expresa la conclusión única de la presentación en una oración. Cada diapositiva debe avanzar esa oración; si una diapositiva no lo hace, elimínala o muévela a un apéndice. El espectador debería poder recordar la columna vertebral después de verlo una vez.
- Un mensaje por diapositiva. Una diapositiva hace exactamente un punto: su título es ese punto, expresado como una afirmación ("La deserción es nuestro verdadero impuesto al crecimiento"), no como una etiqueta ("Deserción"). Dos ideas significan dos diapositivas.
- Las transiciones transmiten lógica, no solo movimiento. El corte entre diapositivas debe responder "¿y qué sigue?" — por lo tanto, pero, lo que significa, aquí está la prueba. Haz coincidir el movimiento con el paso lógico: un fundido suave para "y además", un empuje más grande para "nuevo acto". Una transición que no marca un paso lógico es solo decoración.
- Abre con un gancho, cierra con un CTA. La primera diapositiva capta la atención en ~5s — una pregunta incisiva, una estadística sorprendente, lo que está en juego — no una agenda o un logotipo estático. La última diapositiva indica la acción única que deseas ("Inicia el piloto", "Invierte $2M por el 15%"), mantenida estática como el marco de la conclusión.
Tensión → resolución (la columna vertebral del pitch)
Un pitch es un drama, no una lista de características. Secuéncialo para que la tensión aumente y luego se resuelva — cada acto prepara el siguiente.
| Acto | Momento | Trabajo |
|---|---|---|
| Problema | "Esto es lo que está roto / en juego" | Crear tensión que el espectador sienta |
| Perspectiva | "Esto es lo que todos pasan por alto" | El giro no obvio; ganar la solución |
| Solución | "Aquí está nuestra respuesta" | Resolver la tensión que el problema creó |
| Prueba | "Aquí está por qué funciona" | Tracción, demo, números |
| Petición | "Esto es lo que queremos" | Un CTA concreto |
No reveles la solución antes de que el problema haya calado — una solución inmerecida se siente como una característica, no como un alivio. Asigna tus diapositivas a estos actos; si falta un acto, el argumento tiene un agujero.
Ritmo: mantén la construcción sincronizada con la voz
El hilo conductor se desarrolla en el tiempo, por lo que la construcción en pantalla y la locución deben avanzar juntas — la narración es dueña del reloj (siguiente sección), y las revelaciones se programan contra él para que el espectador lea la línea mientras se dice, nunca antes. Un mensaje por diapositiva hace esto natural: una diapositiva transmite un punto durante exactamente el tiempo que la voz lo argumenta, luego la transición marca el paso lógico al siguiente. Una narración larga sobre un punto significa dividir la diapositiva, no apresurar la construcción.
La regla de oro: la narración es dueña del reloj
Cada diapositiva dura exactamente lo que dura el audio de su narración, más un pequeño margen. Mide la duración real de cada clip de locución, conviértelo a fotogramas y haz que esa sea la duración de la diapositiva. Nunca calcules a ojo "esta diapositiva parece durar ~5s" — siempre se desvía y el audio se corta o se queda sin sonido.
import { getAudioDurationInSeconds } from "@remotion/media-utils";
// En un paso calculateMetadata() / construcción de Remotion, por diapositiva:
const sec = await getAudioDurationInSeconds(slide.audioUrl);
const HANDLE = 0.4; // margen de respiro después de que termina la voz
slide.durationInFrames = Math.ceil((sec + HANDLE) * fps);
Luego, las revelaciones dentro de la diapositiva se programan contra esa duración — los puntos aparecen en las palabras, no en una cuadrícula fija.
Revelaciones de construcción: animar para revelar, nunca para decorar
El objetivo de una construcción es el ritmo: mostrar cada elemento cuando la narración lo alcanza, para que el espectador lea la línea que se está diciendo, no tres líneas adelante. Escalona los elementos; mantén los títulos, logotipos y formas de fondo estáticos.
| Opción | Recomendación | Por qué |
|---|---|---|
| Movimiento de entrada | fundido + ascenso de 12–24px | Pulido, tranquilo; se lee como "llegando" |
| Duración por elemento | 0.25–0.5s | Lo suficientemente rápido para fluir, lo suficientemente lento para registrarse |
| Espaciado entre viñetas | 0.15–0.4s | Secuencial, no un muro de texto |
| Evitar | vuelo, giro, rebote, máquina de escribir | Se lee como decoración; compite con la voz |
Conduce el escalonamiento con useCurrentFrame() para que se mantenga sincronizado con el audio renderizado (consulta references/slide-components.md para el componente completo).
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
const Bullet: React.FC<{ index: number; children: React.ReactNode }> = ({ index, children }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const STAGGER = 8; // fotogramas entre viñetas (~0.27s @ 30fps)
const enter = frame - index * STAGGER; // cada viñeta comienza más tarde
const p = spring({ frame: enter, fps, config: { damping: 200 }, durationInFrames: 12 });
return (
<li style={{ opacity: p, transform: `translateY(${interpolate(p, [0, 1], [18, 0])}px)` }}>
{children}
</li>
);
};
Transiciones entre diapositivas
Secuencia las diapositivas con <TransitionSeries> de @remotion/transitions. Cada diapositiva es una Sequence con su durationInFrames derivado de la narración; una Transition se sitúa entre ellas. Mantén las transiciones sutiles (fundido corto o deslizamiento suave) — el contenido es la estrella, y una transición recargada en cada corte cansa rápidamente.
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
<TransitionSeries>
{slides.map((s, i) => (
<React.Fragment key={s.id}>
<TransitionSeries.Sequence durationInFrames={s.durationInFrames}>
<Slide {...s} />
</TransitionSeries.Sequence>
{i < slides.length - 1 && (
<TransitionSeries.Transition
timing={linearTiming({ durationInFrames: 15 })}
presentation={fade()}
/>
)}
</React.Fragment>
))}
</TransitionSeries>
Reserva una transición más grande (un deslizamiento/empuje) solo para separadores de sección — señala "nuevo tema" y se gana el movimiento extra. Una transición toma prestados fotogramas de ambos vecinos, así que suma su longitud al presupuesto de la diapositiva si la narración de una diapositiva debe reproducirse completa. Consulta references/sequencing.md.
Título y separadores de sección
Una tarjeta de título y los separadores de sección le dan ritmo al video y permiten que el espectador respire entre diapositivas densas. Trata un separador como su propia "diapositiva" corta: un número/palabra de sección grande, el título de la sección, una pausa de ~1.5–2s, y una transición más pronunciada a cada lado. Mantén el lenguaje visual del separador (color, tipo) consistente para que se lea como puntuación, no como un video diferente.
Mantén el texto legible y acorde a la marca
Las diapositivas tienen mucho texto, por lo que la legibilidad es lo más importante.
- Escala tipográfica, no escala de presentación. Una presentación vista en un portátil ≠ un video visto en un feed. Aumenta el cuerpo a ≥ 28–32px a 1080p; títulos a 56–80px. Si una diapositiva necesita una nota al pie de 16px para caber, necesita dividirse en dos diapositivas.
- Una idea por diapositiva. Si la narración de una diapositiva se alarga, divídela — nunca reduzcas el tipo de letra para que quepa.
- Contraste + márgenes seguros. Mantén una relación de contraste ≥ 4.5:1; mantén todo el contenido dentro del 90% central para que sobreviva al recorte de la plataforma.
- Fija la marca en un objeto de tema. Los colores, fuentes, logotipo y espaciado viven en un solo
themepara que cada diapositiva sea consistente y un cambio de marca sea un cambio de una línea.
export const theme = {
bg: "#0B0B12", fg: "#F5F5F7", accent: "#6C5CE7",
font: "Inter, system-ui, sans-serif",
titlePx: 72, bodyPx: 30, maxWidthPct: 90,
} as const;
Flujo de trabajo
- Esquema → guion. Una diapositiva = una idea + la(s) línea(s) exacta(s) de narración. Esta es la fuente de verdad.
- Generar/grabar narración por diapositiva. Un archivo de audio por diapositiva (TTS o grabado).
- Medir audio → establecer duraciones de diapositiva.
getAudioDurationInSeconds→ fotogramas (la regla anterior). - Construir componentes de diapositiva con revelaciones escalonadas vinculadas a
useCurrentFrame(). - Secuenciar con
<TransitionSeries>; añadir título + separadores de sección. - Montar el audio de cada diapositiva dentro de su
Sequencepara que la voz y las imágenes nunca se desincronicen. - Pase de legibilidad/marca, luego renderizar a MP4.
Lista de verificación de salida
- El
durationInFramesde cada diapositiva se deriva de su audio de narración, no se adivina. - El audio de cada diapositiva está montado dentro de su propia
Sequence(imágenes + voz bloqueadas juntas). - Las viñetas se revelan secuencialmente mediante
useCurrentFrame(); títulos/logotipos estáticos. - Las revelaciones son fundido+ascenso, 0.25–0.5s, sin efectos decorativos.
- Las transiciones entre diapositivas son sutiles; transiciones más grandes solo en separadores de sección.
- Tipo de cuerpo ≥ 28px @ 1080p, contraste ≥ 4.5:1, contenido dentro del 90% central.
- Una idea por diapositiva; la narración larga divide la diapositiva en lugar de reducir el tipo.
Entregar y verificar (fotogramas renderizados → MP4)
Helper empaquetado (
scripts/): organiza tus fotogramas conscripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png, luego verifica la codificación conscripts/probe-mp4.sh out.mp4 [WxH] [fps]. Consultascripts/README.md.
Remotion es determinista por fotograma — cada construcción de viñeta, transición y posición de diapositiva es una función pura de useCurrentFrame(), por lo que puedes renderizar cualquier fotograma exacto sin necesidad de un harness de búsqueda. El entregable es un MP4 narrado, por lo que la inspección de fotogramas estáticos detecta un título recortado, un color fuera de la marca o una viñeta que se desborda antes de desperdiciar una codificación completa.
Contrato de salida:
- Un proyecto de Remotion con la presentación registrada (
<Composition>+ esquema zod +defaultProps), todo el movimiento impulsado por fotogramas (sin temporizadores /Date.now()/Math.random()); audio por diapositiva montado dentro de su propiaSequence. - Entregable = el
out/*.mp4renderizado (más el proyecto, para que el usuario pueda volver a renderizar con nuevas diapositivas/narración). - Las duraciones de las diapositivas se derivan de la narración — calcula el total + el
durationInFramespor diapositiva encalculateMetadata(mide cada clip de audio), nunca a mano.
Bucle de verificación — renderizar fotogramas → inspeccionar → codificar. Renderiza primero fotogramas individuales (baratos, sin codificación de video), luego codifica solo una vez que cada diapositiva se construya y se vea bien.
# 1. Fotogramas exactos — con las props ENTREGADAS. Coloca uno dentro del estado estable de cada diapositiva:
npx remotion still Deck out/f-title.png --frame=20 --props='{"slides":[...]}' # tarjeta de título estable
npx remotion still Deck out/f-mid.png --frame=240 --props='{"slides":[...]}' # diapositiva de contenido, viñetas construidas
npx remotion still Deck out/f-end.png --frame=899 --props='{"slides":[...]}' # último fotograma = durationInFrames - 1
# 2. Inspecciona cada PNG — FIDELIDAD (texto de diapositiva exacto, números/etiquetas correctos, colores/fuentes de marca aplicados)
# Y artefactos (desbordamiento de texto, tamaño de cuerpo demasiado pequeño, contenido fuera del recorte seguro del 90% central,
# fuente faltante, bajo contraste, viñeta atrapada a medio construir donde la diapositiva debería estar estable).
# 3. Solo después de que los fotogramas estén bien, codifica:
npx remotion render Deck out/deck.mp4 --props='{"slides":[...]}'
- Usa
npx remotion compositionspara leer eldurationInFrames/fpsde la presentación y elegir el fotograma final; muestra un fotograma dentro del tiempo de espera de cada diapositiva, no en una transición, para juzgar el estado construido. - Basado en datos / por lotes: verifica UNA presentación representativa (diapositivas reales + narración) mediante fotogramas antes de renderizar cada variante — detecta un error de escala tipográfica o desbordamiento una vez, no por presentación.
- GIF de demostración para el README gratis:
npx remotion render Deck out/demo.gif --codec=gif.
Antes de terminar:
npx remotion stillrenderiza limpiamente en el título, una diapositiva de contenido y el último fotograma — sin errores, sin fuentes faltantes.- El texto de la diapositiva es exacto, tipo de cuerpo ≥ 28px @ 1080p, contraste ≥ 4.5:1, todo el contenido dentro del 90% central en cada fotograma.
- Solo impulsado por fotogramas — sin
Date.now()/Math.random()/ temporizadores de biblioteca (el determinismo se mantiene en CI). - Las props entregadas se renderizan correctamente (no solo
defaultProps) — diapositivas correctas, narración montada, duraciones del audio. - MP4 completo codificado y se reproduce (voz + imágenes bloqueadas); (opcional) GIF renderizado para el README.
Archivos de referencia
references/slide-components.md— componentesSlide,BulletList,TitleCardySectionDividercompletos y ejecutables de Remotion con un tema compartido y narración por diapositiva montada mediante<Audio>.references/sequencing.md— el secuenciador completo de la presentación:calculateMetadataque mide cada clip de narración y establece las duraciones total y por diapositiva, ensamblaje<TransitionSeries>, contabilidad del presupuesto de fotogramas de transición y un flujo de datos de esquema JSON de presentación a video.