En este artículo
- Qué es Remotion y por qué debería importarte
- Remotion vs. las alternativas: tabla honesta
- Instalación paso a paso (5 minutos)
- Tu primer vídeo en 20 líneas de código
- Animaciones que parecen de estudio
- Presentaciones animadas (adiós PowerPoint)
- 8 templates listos para copiar
- Videos con datos dinámicos: el superpoder
- Remotion + IA: genera videos con Claude Code
- Audio, voiceover y subtítulos
- Renderizado: local, Lambda y GitHub Actions
- Pipeline de producción real
- 9 errores que vas a cometer (y cómo evitarlos)
- Casos de uso reales
- Preguntas frecuentes
Resumen rápido
Remotion es un framework open-source que permite crear videos y presentaciones profesionales escribiendo código React. Es gratis para la mayoría de usuarios, se integra con IA para automatizar la producción, y permite generar cientos de videos distintos sin tocar una interfaz gráfica. En esta guía vas a aprender desde la instalación hasta montar un pipeline completo de producción.
Qué es Remotion y por qué debería importarte
Piensa en esto: cada vez que necesitas un vídeo para redes sociales, un tutorial animado para tu curso, o una presentación que no parezca sacada de 2008, abres Canva. O Premiere. O contratas a alguien. Y cada vez que cambias un dato (un precio, una fecha, un nombre) tienes que repetir todo el proceso manualmente.
Remotion cambia esa ecuación por completo.
Remotion es un framework de código abierto que convierte componentes React en vídeo. Si sabes hacer una página web con React (o incluso si no sabes y usas IA para generarla), puedes crear videos de calidad profesional. No es una metáfora: literalmente escribes JSX, CSS y TypeScript, y Remotion lo renderiza fotograma a fotograma en un MP4, WebM o GIF.
Esto tiene implicaciones que no son obvias a primera vista:
- Cada vídeo es una función. Le pasas parámetros diferentes (título, datos, colores, idioma) y genera un vídeo distinto. Un template, infinitos resultados.
- Se puede automatizar. Un script que lee datos de una base de datos y genera 500 videos personalizados en una noche. Sin operador humano.
- Se versiona con Git. Tus videos tienen historial de cambios, ramas, pull requests. Puedes colaborar en un vídeo como colaboras en código.
- Se puede integrar con IA. Claude Code puede generar el código de un vídeo Remotion a partir de una descripción en lenguaje natural. Veremos cómo más adelante.
Remotion fue creado por Jonny Burger en 2021 y ha crecido hasta tener más de 20.000 estrellas en GitHub. Lo usan empresas como Shopify, Stripe y GitHub para generar videos programáticos. No es un proyecto experimental: es producción real en compañías que facturan miles de millones.
Para quién es Remotion (y para quién no)
Es para ti si:
- Necesitas generar videos de forma recurrente (no uno puntual, sino muchos).
- Quieres automatizar la producción de contenido visual.
- Sabes algo de React o estás dispuesto a aprender (o a usar IA para generar el código).
- Valoras el control total sobre el resultado: cada pixel, cada fotograma, cada transición.
- Tienes un presupuesto limitado (o nulo) para herramientas de vídeo.
Probablemente no es para ti si:
- Necesitas editar un vídeo grabado con cámara (cortes, color grading, audio sync). Para eso usa DaVinci Resolve (también gratis).
- Quieres arrastrar y soltar sin tocar código y no estás dispuesto a usar IA como intermediario.
- Solo necesitas un vídeo puntual y no te importa el proceso manual.
Aprende a automatizar con IA desde cero
El Módulo 07 de IAcademy cubre automatización con n8n, APIs y herramientas programáticas como Remotion. Accede gratis al Módulo 03 para empezar.
Acceder al Módulo 03 gratisRemotion vs. las alternativas: tabla honesta
Antes de invertir tiempo en aprender una herramienta, quieres saber cómo se compara con lo que ya conoces. Esta tabla no es marketing: es una evaluación honesta basada en uso real.
| Criterio | Remotion | Canva Vídeo | Gamma | After Effects | FFmpeg |
|---|---|---|---|---|---|
| Precio | Gratis* | 12,99 EUR/mes | 8 USD/mes | 24,19 EUR/mes | Gratis |
| Automatizable | Total | Limitado (API) | No | Scripts ExtendScript | Total |
| Curva aprendizaje | Media (React) | Baja | Baja | Alta | Alta |
| Calidad visual | Profesional | Buena | Buena | Profesional | Básica |
| Presentaciones | Sí (como vídeo) | Sí | Nativo | No | No |
| Batch (100+ videos) | Nativo | Manual | No | Posible (complejo) | Nativo |
| IA integrable | Total (Claude, GPT) | Limitado | Nativo | Plugins | No |
| Ideal para | Producción a escala | Videos puntuales | Presentaciones rápidas | Post-producción | Procesamiento batch |
La conclusión es clara: si necesitas un vídeo puntual y rápido, Canva o Gamma son más prácticos. Si necesitas producción recurrente, automatizada y con control total, Remotion no tiene rival en su franja de precio.
Nota sobre la licencia
Remotion usa una licencia personalizada (no MIT ni GPL). Es gratuito si tu empresa factura menos de 150.000 USD anuales. Para proyectos personales, educativos, organizaciones sin ánimo de lucro y la mayoría de startups en fase temprana, es completamente gratis. Si tu empresa crece por encima de ese umbral (enhorabuena), entonces necesitas la licencia comercial. Los detalles están en el repositorio oficial.
Instalación paso a paso (5 minutos)
Remotion funciona sobre Node.js. Si ya tienes Node 18+ instalado, son tres comandos. Si no, empezamos por ahí.
Requisitos previos
- Node.js 18 o superior. Comprueba con
node --version. Si no lo tienes, instala la versión LTS. - npm, yarn o pnpm. Cualquiera vale. Los ejemplos usan npm porque viene con Node.
- Chrome o Chromium. Remotion usa un navegador headless para renderizar. Normalmente lo instala automáticamente.
Crear un proyecto nuevo
# Crear proyecto Remotion con el template por defecto
npx create-video@latest mi-primer-video
# Entrar al directorio
cd mi-primer-video
# Instalar dependencias
npm install
# Arrancar el preview en el navegador
npm start
Cuando ejecutes npm start, se abre el Remotion Studio en tu navegador. Es un reproductor interactivo donde ves tu vídeo en tiempo real mientras editas el código. Cada vez que guardas un archivo, el preview se actualiza al instante.
El proyecto creado tiene esta estructura:
mi-primer-video/
├── src/
│ ├── Root.tsx # Punto de entrada: define las composiciones
│ ├── HelloWorld.tsx # Tu primer componente de video
│ ├── Logo.tsx # Componente del logo animado
│ └── Subtitle.tsx # Componente de subtitulos
├── public/ # Assets estaticos (imagenes, fuentes)
├── remotion.config.ts # Configuracion del proyecto
├── package.json
└── tsconfig.json
Cada archivo .tsx dentro de src/ es un componente React normal. La diferencia es que en lugar de responder a clicks del usuario, responde al tiempo: el frame actual del vídeo.
Configuración básica
El archivo remotion.config.ts controla el comportamiento global:
// remotion.config.ts
import { Config } from "@remotion/cli/config";
Config.setVideoImageFormat("jpeg"); // Formato de cada frame
Config.setOverwriteOutput(true); // Sobreescribir al renderizar
Config.setConcurrency(4); // Frames en paralelo
Por ahora no necesitas cambiar nada. Los valores por defecto funcionan bien para empezar.
Tu primer vídeo en 20 líneas de código
Vamos a crear un vídeo desde cero. Nada de templates complicados. Un componente React que muestre un texto animado sobre un fondo con gradiente. Algo que puedas entender línea a línea.
// src/MiPrimerVideo.tsx
import { AbsoluteFill, useCurrentFrame, interpolate } from "remotion";
export const MiPrimerVideo: React.FC = () => {
const frame = useCurrentFrame();
// Opacidad: aparece de 0 a 1 en los primeros 30 frames
const opacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: "clamp",
});
// El texto sube 40px durante los primeros 30 frames
const translateY = interpolate(frame, [0, 30], [40, 0], {
extrapolateRight: "clamp",
});
return (
<AbsoluteFill
style={{
background: "linear-gradient(135deg, #0f0f18, #1a1a3e)",
justifyContent: "center",
alignItems: "center",
}}
>
<h1
style={{
color: "#fff",
fontSize: 72,
fontFamily: "Inter, sans-serif",
fontWeight: 700,
opacity,
transform: `translateY(${translateY}px)`,
}}
>
Tu primer video con Remotion
</h1>
</AbsoluteFill>
);
};
Ahora registramos este componente como una composición en Root.tsx:
// src/Root.tsx
import { Composition } from "remotion";
import { MiPrimerVideo } from "./MiPrimerVideo";
export const RemotionRoot: React.FC = () => {
return (
<Composition
id="MiPrimerVideo"
component={MiPrimerVideo}
durationInFrames={150} // 5 segundos a 30fps
fps={30}
width={1920}
height={1080}
/>
);
};
Eso es todo. Ejecuta npm start y verás tu vídeo en el navegador. Un texto blanco que aparece con un fade-in suave sobre un fondo oscuro con gradiente. Cinco segundos, Full HD, sin pagar un céntimo.
Entender el modelo mental
Hay tres conceptos que necesitas interiorizar:
useCurrentFrame()devuelve el número de frame actual (0, 1, 2, 3...). Es el equivalente al "tiempo" en un vídeo. Si tu vídeo va a 30 fps y dura 150 frames, tienes 5 segundos de vídeo.interpolate()mapea un rango de entrada a un rango de salida. Le dices "del frame 0 al 30, lleva la opacidad de 0 a 1" y calcula el valor exacto en cada frame. Es tu herramienta principal para animaciones.<AbsoluteFill>es un div que ocupa todo el canvas del vídeo. Es el equivalente al "fondo" de tu composición. Puedes anidar variosAbsoluteFillpara crear capas.
Con estos tres conceptos puedes crear cualquier animación. Todo lo demás (transiciones, secuencias, audio) se construye sobre esta base.
interpolate() y CSS puro puedes conseguir el 90% de las animaciones que necesitas. Añade complejidad solo cuando la necesites.Animaciones que parecen de estudio
La diferencia entre un vídeo amateur y uno profesional no está en los efectos: está en la suavidad de las transiciones, el timing y la coherencia visual. Remotion te da control absoluto sobre todo esto.
Easings: el secreto del movimiento natural
El movimiento lineal (de A a B a velocidad constante) se ve robótico. El movimiento natural tiene aceleración y deceleración. Remotion incluye funciones de easing para esto:
import { interpolate, Easing } from "remotion";
// Movimiento con aceleracion suave
const scale = interpolate(frame, [0, 30], [0.8, 1], {
extrapolateRight: "clamp",
easing: Easing.out(Easing.cubic), // Empieza rapido, frena suave
});
// Efecto rebote
const bounce = interpolate(frame, [0, 40], [0, 1], {
extrapolateRight: "clamp",
easing: Easing.bounce, // Rebota al final
});
// Spring (resorte) - el mas natural
import { spring, useVideoConfig } from "remotion";
const { fps } = useVideoConfig();
const springValue = spring({
frame,
fps,
config: { damping: 12, stiffness: 200 },
});
La función spring() es la que más vas a usar. Simula un resorte físico y produce el movimiento más natural. Ajusta damping (cuanto frena) y stiffness (cuanto "salta") hasta que consigas el efecto que buscas.
Secuencias: organizar el tiempo
Un vídeo real tiene múltiples elementos que aparecen en momentos distintos. El componente <Sequence> controla cuándo aparece cada parte:
import { Sequence, AbsoluteFill } from "remotion";
export const VideoCompleto: React.FC = () => {
return (
<AbsoluteFill style={{ background: "#0f0f18" }}>
{/* El titulo aparece desde el frame 0 */}
<Sequence from={0} durationInFrames={90}>
<TituloAnimado text="Remotion es increible" />
</Sequence>
{/* El subtitulo aparece en el frame 30 */}
<Sequence from={30} durationInFrames={60}>
<Subtitulo text="Videos con codigo React" />
</Sequence>
{/* El CTA aparece en el frame 90 */}
<Sequence from={90}>
<CallToAction url="iacedemy.com/free" />
</Sequence>
</AbsoluteFill>
);
};
Cada <Sequence> resetea el contador de frames internamente. Es decir, dentro de <TituloAnimado>, useCurrentFrame() empieza en 0 aunque en el vídeo global ese componente aparezca en el frame 30. Esto hace que cada componente sea independiente y reutilizable.
Transiciones entre escenas
El paquete @remotion/transitions añade transiciones cinematográficas:
npm install @remotion/transitions
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";
import { wipe } from "@remotion/transitions/wipe";
export const VideoConTransiciones: React.FC = () => {
return (
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={90}>
<Escena1 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={fade()}
timing={linearTiming({ durationInFrames: 20 })}
/>
<TransitionSeries.Sequence durationInFrames={90}>
<Escena2 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={slide({ direction: "from-left" })}
timing={linearTiming({ durationInFrames: 15 })}
/>
<TransitionSeries.Sequence durationInFrames={120}>
<Escena3 />
</TransitionSeries.Sequence>
</TransitionSeries>
);
};
Transiciones disponibles: fade, slide, wipe, flip, clockWipe, y más. También puedes crear transiciones custom con CSS o WebGL.
Presentaciones animadas (adiós PowerPoint)
Una de las aplicaciones más potentes de Remotion es generar presentaciones que no parecen presentaciones. En lugar de slides estáticas con bullet points, produces un vídeo fluido con transiciones cinematográficas, datos animados y una narrativa visual coherente.
Estructura de una presentación en Remotion
Cada slide es un componente React. La presentación es una secuencia de slides con transiciones:
// src/Presentacion.tsx
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { slide } from "@remotion/transitions/slide";
// Datos de las slides
const slides = [
{
titulo: "El Problema",
cuerpo: "El 73% de los profesionales dedican mas de 4 horas semanales a crear presentaciones.",
color: "#ef4444",
},
{
titulo: "La Solucion",
cuerpo: "Remotion genera presentaciones animadas desde codigo. Escribe una vez, produce infinitas variantes.",
color: "#3b82f6",
},
{
titulo: "Los Resultados",
cuerpo: "87% menos tiempo de produccion. 100% personalizable. 0 EUR de coste.",
color: "#22c55e",
},
{
titulo: "Siguiente Paso",
cuerpo: "Aprende Remotion en IAcademy. Modulo 03 gratuito. Empieza hoy.",
color: "#f59e0b",
},
];
export const Presentacion: React.FC = () => {
return (
<TransitionSeries>
{slides.map((s, i) => (
<>
{i > 0 && (
<TransitionSeries.Transition
presentation={slide({ direction: "from-right" })}
timing={linearTiming({ durationInFrames: 15 })}
/>
)}
<TransitionSeries.Sequence durationInFrames={120} key={i}>
<Slide titulo={s.titulo} cuerpo={s.cuerpo} color={s.color} />
</TransitionSeries.Sequence>
</>
))}
</TransitionSeries>
);
};
La clave: los datos de la presentación están separados del diseño. Puedes cambiar el contenido de las slides sin tocar el componente visual. Puedes alimentar los datos desde un JSON, una base de datos o una llamada a una API.
Componente Slide reutilizable
// src/Slide.tsx
import { AbsoluteFill, useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
interface SlideProps {
titulo: string;
cuerpo: string;
color: string;
}
export const Slide: React.FC<SlideProps> = ({ titulo, cuerpo, color }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const titleSpring = spring({ frame, fps, config: { damping: 15 } });
const bodyOpacity = interpolate(frame, [15, 35], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<AbsoluteFill
style={{
background: `linear-gradient(135deg, #0f0f18 60%, ${color}22)`,
justifyContent: "center",
padding: "0 120px",
}}
>
<div
style={{
borderLeft: `4px solid ${color}`,
paddingLeft: 32,
transform: `translateY(${(1 - titleSpring) * 30}px)`,
opacity: titleSpring,
}}
>
<h2 style={{
color: "#fff",
fontSize: 64,
fontFamily: "Inter, sans-serif",
fontWeight: 700,
margin: "0 0 24px",
}}>
{titulo}
</h2>
<p style={{
color: "rgba(255,255,255,0.75)",
fontSize: 28,
fontFamily: "Inter, sans-serif",
lineHeight: 1.6,
maxWidth: 800,
opacity: bodyOpacity,
}}>
{cuerpo}
</p>
</div>
</AbsoluteFill>
);
};
Con este componente y el array de datos, ya tienes una presentación animada completa. Cada slide tiene un título que entra con spring y un cuerpo que aparece con fade. Las transiciones entre slides son deslizamientos laterales. El resultado es un vídeo MP4 que puedes reproducir en cualquier dispositivo, compartir por enlace o incrustar en una web.
Ventaja sobre PowerPoint y Google Slides
Un archivo .pptx solo funciona en aplicaciones de presentación. Un vídeo MP4 funciona en todas partes: redes sociales, WhatsApp, email, webs, televisores. Además, la audiencia no puede "saltarse slides": ven la presentación como tú quieres que la vean, con el ritmo que tú controlas.
8 templates listos para copiar
No necesitas empezar de cero. Estos templates cubren los casos de uso más comunes. Copia el que necesites y modifícalo.
1. Intro para YouTube
// Duracion: 3s | Resolucion: 1920x1080
// Texto central con efecto glitch + logo que aparece con spring
export const YoutubeIntro: React.FC<{ canal: string }> = ({ canal }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const logoScale = spring({ frame: frame - 30, fps, config: { damping: 10 } });
return (
<AbsoluteFill style={{ background: "#0f0f18", justifyContent: "center", alignItems: "center" }}>
<Sequence from={0} durationInFrames={45}>
<GlitchText text={canal} />
</Sequence>
<Sequence from={30}>
<div style={{ transform: `scale(${logoScale})` }}>
<Logo />
</div>
</Sequence>
</AbsoluteFill>
);
};
2. Social media clip (9:16 vertical)
// Resolucion: 1080x1920 (Instagram Reels, TikTok, YouTube Shorts)
<Composition
id="SocialClip"
component={SocialClip}
width={1080}
height={1920}
fps={30}
durationInFrames={450} // 15 segundos
/>
3. Contador animado (ideal para datos)
export const Contador: React.FC<{ valor: number; sufijo: string }> = ({ valor, sufijo }) => {
const frame = useCurrentFrame();
const numero = Math.round(interpolate(frame, [0, 60], [0, valor], {
extrapolateRight: "clamp",
easing: Easing.out(Easing.cubic),
}));
return (
<div style={{ fontSize: 96, fontWeight: 800, color: "#ef4444", fontVariantNumeric: "tabular-nums" }}>
{numero.toLocaleString("es-ES")}{sufijo}
</div>
);
};
4. Comparativa lado a lado
// Dos columnas que entran desde lados opuestos
export const Comparativa: React.FC<{ izquierda: string; derecha: string }> = (props) => {
const frame = useCurrentFrame();
const slideIzq = interpolate(frame, [0, 20], [-100, 0], { extrapolateRight: "clamp" });
const slideDer = interpolate(frame, [0, 20], [100, 0], { extrapolateRight: "clamp" });
return (
<AbsoluteFill style={{ flexDirection: "row" }}>
<div style={{ flex: 1, background: "#1a1a2e", transform: `translateX(${slideIzq}%)`, padding: 60 }}>
<h3 style={{ color: "#ef4444" }}>{props.izquierda}</h3>
</div>
<div style={{ flex: 1, background: "#0f0f18", transform: `translateX(${slideDer}%)`, padding: 60 }}>
<h3 style={{ color: "#22c55e" }}>{props.derecha}</h3>
</div>
</AbsoluteFill>
);
};
5. Testimonio con cita
// Cita que aparece palabra por palabra
export const Testimonio: React.FC<{ texto: string; autor: string }> = ({ texto, autor }) => {
const frame = useCurrentFrame();
const palabras = texto.split(" ");
const palabrasVisibles = Math.floor(interpolate(frame, [0, 90], [0, palabras.length], {
extrapolateRight: "clamp",
}));
return (
<AbsoluteFill style={{ background: "#0f0f18", justifyContent: "center", padding: "0 140px" }}>
<p style={{ fontSize: 42, color: "#fff", lineHeight: 1.6, fontStyle: "italic" }}>
"{palabras.slice(0, palabrasVisibles).join(" ")}"
</p>
<Sequence from={100}>
<p style={{ fontSize: 20, color: "rgba(255,255,255,0.5)", marginTop: 24 }}>
— {autor}
</p>
</Sequence>
</AbsoluteFill>
);
};
6. Gráfico de barras animado
// Barras que crecen progresivamente
export const BarChart: React.FC<{ datos: { label: string; valor: number }[] }> = ({ datos }) => {
const frame = useCurrentFrame();
const max = Math.max(...datos.map(d => d.valor));
return (
<AbsoluteFill style={{ background: "#0f0f18", padding: 80, justifyContent: "flex-end" }}>
<div style={{ display: "flex", gap: 24, alignItems: "flex-end", height: "60%" }}>
{datos.map((d, i) => {
const height = interpolate(frame, [i * 10, i * 10 + 30], [0, (d.valor / max) * 100], {
extrapolateLeft: "clamp", extrapolateRight: "clamp",
});
return (
<div key={i} style={{ flex: 1, textAlign: "center" }}>
<div style={{
height: `${height}%`, background: `hsl(${i * 60}, 70%, 60%)`,
borderRadius: "8px 8px 0 0", transition: "height 0.1s",
}} />
<p style={{ color: "#aaa", fontSize: 14, marginTop: 12 }}>{d.label}</p>
</div>
);
})}
</div>
</AbsoluteFill>
);
};
7. Lower third (nombre + cargo)
// Banner inferior tipo noticias de television
export const LowerThird: React.FC<{ nombre: string; cargo: string }> = ({ nombre, cargo }) => {
const frame = useCurrentFrame();
const slideIn = interpolate(frame, [0, 15], [-200, 0], {
extrapolateRight: "clamp", easing: Easing.out(Easing.cubic),
});
return (
<AbsoluteFill>
<div style={{
position: "absolute", bottom: 80, left: 60,
transform: `translateX(${slideIn}px)`,
background: "rgba(15,15,24,0.9)", padding: "16px 32px",
borderLeft: "4px solid #ef4444", borderRadius: "0 12px 12px 0",
}}>
<p style={{ color: "#fff", fontSize: 24, fontWeight: 700, margin: 0 }}>{nombre}</p>
<p style={{ color: "rgba(255,255,255,0.6)", fontSize: 16, margin: "4px 0 0" }}>{cargo}</p>
</div>
</AbsoluteFill>
);
};
8. Countdown / cuenta atrás
export const Countdown: React.FC<{ desde: number }> = ({ desde }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const segundosRestantes = Math.max(0, desde - Math.floor(frame / fps));
const pulso = spring({ frame: frame % fps, fps, config: { damping: 8, mass: 0.5 } });
return (
<AbsoluteFill style={{ background: "#0f0f18", justifyContent: "center", alignItems: "center" }}>
<div style={{
fontSize: 200, fontWeight: 900, color: "#ef4444",
transform: `scale(${0.9 + pulso * 0.1})`,
fontVariantNumeric: "tabular-nums",
}}>
{segundosRestantes}
</div>
</AbsoluteFill>
);
};
Descarga la guía maestra de Claude (gratis)
Prompts avanzados, workflows y automatización con herramientas como Remotion. PDF directo a tu email.
Videos con datos dinámicos: el superpoder
Aquí es donde Remotion deja de ser "una herramienta de vídeo bonita" y se convierte en algo transformador. La capacidad de generar videos a partir de datos es lo que justifica aprender a usarlo.
El concepto: datos como props
En React, un componente recibe datos a través de props. En Remotion, un vídeo recibe datos exactamente igual. Defines un schema de datos y el vídeo se adapta automáticamente:
import { z } from "zod";
// Schema de datos del video
export const videoSchema = z.object({
titulo: z.string(),
estadisticas: z.array(z.object({
label: z.string(),
valor: z.number(),
})),
colorPrincipal: z.string().default("#ef4444"),
logoUrl: z.string().optional(),
});
// El componente usa los datos
export const VideoConDatos: React.FC<z.infer<typeof videoSchema>> = (props) => {
return (
<AbsoluteFill>
<Titulo text={props.titulo} color={props.colorPrincipal} />
<BarChart datos={props.estadisticas} />
{props.logoUrl && <Logo url={props.logoUrl} />}
</AbsoluteFill>
);
};
// Registro con schema y datos por defecto
<Composition
id="VideoConDatos"
component={VideoConDatos}
schema={videoSchema}
defaultProps={{
titulo: "Metricas Q3 2026",
estadisticas: [
{ label: "Usuarios", valor: 45200 },
{ label: "Revenue", valor: 127000 },
{ label: "NPS", valor: 72 },
],
colorPrincipal: "#ef4444",
}}
durationInFrames={300}
fps={30}
width={1920}
height={1080}
/>
Renderizar con datos distintos desde la CLI
# Renderizar un video con datos custom
npx remotion render VideoConDatos --props='{"titulo":"Metricas Q4","estadisticas":[{"label":"Usuarios","valor":67800},{"label":"Revenue","valor":198000}]}'
# O leer los datos desde un archivo JSON
npx remotion render VideoConDatos --props=./datos-q4.json
Batch rendering: 100 videos de una vez
El caso de uso killer. Imagina que tienes una lista de clientes y quieres generar un vídeo personalizado para cada uno:
// scripts/batch-render.ts
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
import fs from "fs";
const clientes = JSON.parse(fs.readFileSync("./clientes.json", "utf-8"));
async function main() {
const bundled = await bundle({ entryPoint: "./src/index.ts" });
for (const cliente of clientes) {
const composition = await selectComposition({
serveUrl: bundled,
id: "VideoPersonalizado",
inputProps: {
nombre: cliente.nombre,
empresa: cliente.empresa,
metricas: cliente.metricas,
},
});
await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: `./output/${cliente.id}.mp4`,
});
console.log(`Video generado: ${cliente.nombre}`);
}
}
main();
Ejecutas npx tsx scripts/batch-render.ts y Remotion genera un vídeo MP4 personalizado para cada cliente. Con 100 clientes, tardas minutos en lugar de días.
Remotion + IA: genera videos con Claude Code
Esta es la parte que realmente cambia las reglas del juego. Remotion es código. La IA genera código. La combinación es obvia: puedes describir un vídeo en lenguaje natural y que la IA escriba el código de Remotion por ti.
Flujo básico: descripción natural a vídeo
# En Claude Code, dentro de tu proyecto Remotion:
"Crea un componente Remotion para un video de 15 segundos
en formato 9:16 (vertical) que muestre:
1. Un titulo grande 'Top 5 herramientas IA gratis' con efecto spring
2. Los 5 items apareciendo uno por uno con slide desde la derecha
3. Fondo oscuro con gradiente, texto blanco, acentos en rojo #ef4444
4. Al final, un CTA con 'Mas en iacedemy.com'"
Claude Code genera el componente completo con las animaciones, lo registra como composición en Root.tsx, y puedes previsualizarlo inmediatamente con npm start. Si algo no te convence, iteras con lenguaje natural: "haz que los ítems aparezcan más rápido" o "cambia el fondo a un azul oscuro".
Automatización completa con IA
El flujo más avanzado combina varias capas de IA:
- IA genera el guion. Le das un tema y genera el texto del vídeo: título, puntos clave, CTA.
- IA genera el código Remotion. Toma el guion y produce los componentes React animados.
- Remotion renderiza el vídeo. El código se ejecuta y genera el MP4.
- IA genera los subtítulos. Whisper (OpenAI) o similar transcribe el audio si lo hay.
- Un script distribuye el vídeo. Lo sube a YouTube, lo comparte en redes, lo envía por email.
Todo esto puede correr en un script de Node.js o un workflow de n8n sin intervención humana. La única supervisión necesaria es un checkpoint de aprobación: ves el vídeo renderizado, le das OK, y se distribuye.
Ejemplo: generar infografías animadas con datos de una API
// scripts/infografia-auto.ts
// 1. Obtener datos de la API
const response = await fetch("https://api.ejemplo.com/metricas-semanales");
const datos = await response.json();
// 2. Generar props para el video
const props = {
titulo: `Metricas Semana ${datos.semana}`,
metricas: datos.kpis.map(kpi => ({
label: kpi.nombre,
valor: kpi.valor,
cambio: kpi.cambio_porcentual,
})),
fecha: new Date().toLocaleDateString("es-ES"),
};
// 3. Renderizar
await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: `./output/infografia-sem${datos.semana}.mp4`,
inputProps: props,
});
// 4. Publicar (por ejemplo, via Buffer API)
await publicarEnRedesSociales(`./output/infografia-sem${datos.semana}.mp4`);
Este script puede ejecutarse todos los lunes a las 9:00 con un cron job o un workflow de n8n. Genera la infografía de la semana con datos reales y la pública automáticamente.
Curso completo: 108 módulos de IA aplicada
23 especializaciones por departamento. Automatización, agentes, producción de contenido, desarrollo. Dashboard con progreso y quizzes.
Audio, voiceover y subtítulos
Un vídeo sin audio se siente incompleto. Remotion soporta audio nativo, incluyendo música de fondo, efectos de sonido y voiceover.
Añadir música de fondo
import { Audio, staticFile } from "remotion";
// Dentro de tu composicion
<Audio src={staticFile("musica-fondo.mp3")} volume={0.3} />
El archivo va en la carpeta public/. Puedes controlar el volumen, hacer fade in/out, y sincronizar con las animaciones.
Fade in y fade out del audio
import { Audio, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
const volume = interpolate(
frame,
[0, 30, durationInFrames - 30, durationInFrames],
[0, 0.4, 0.4, 0],
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
);
<Audio src={staticFile("musica.mp3")} volume={volume} />
Voiceover con TTS
Para voiceover, puedes generar el audio con un servicio de text-to-speech (ElevenLabs, Google TTS, Amazon Polly, o incluso modelos locales como Coqui TTS) y luego incluirlo en el vídeo:
// 1. Genera el audio con TTS (puede ser un paso previo en el pipeline)
// elevenlabs generate --text "Bienvenido al video" --voice "Antoni" --output voiceover.mp3
// 2. Incluye el audio en el video
<Audio src={staticFile("voiceover.mp3")} volume={0.9} startFrom={30} />
Subtítulos sincronizados
Remotion tiene un paquete dedicado para subtítulos: @remotion/captions. Puedes generar subtítulos automáticamente desde un archivo de transcripción:
npm install @remotion/captions
import { parseSrt } from "@remotion/captions";
// Lee el archivo .srt
const subtitulos = parseSrt(srtContent);
// Muestra el subtitulo activo para el frame actual
const subtituloActual = subtitulos.find(
(s) => frame >= s.startFrame && frame <= s.endFrame
);
{subtituloActual && (
<div style={{
position: "absolute", bottom: 80, width: "100%", textAlign: "center",
padding: "12px 24px",
}}>
<span style={{
background: "rgba(0,0,0,0.75)", color: "#fff",
fontSize: 28, padding: "8px 20px", borderRadius: 8,
}}>
{subtituloActual.text}
</span>
</div>
)}
El flujo completo para videos con voz: genera el audio con TTS, transcríbelo a SRT (Whisper es perfecto para esto), y Remotion sincroniza los subtítulos con el vídeo automáticamente.
Renderizado: local, Lambda y GitHub Actions
Tienes tres opciones para renderizar, cada una con su caso de uso.
Renderizado local (gratis, sin límite)
# Renderizar en MP4 (H.264)
npx remotion render MiVideo output/video.mp4
# Renderizar en WebM (VP8, mas ligero)
npx remotion render MiVideo output/video.webm --codec=vp8
# Renderizar como GIF (para redes)
npx remotion render MiVideo output/video.gif --every-nth-frame=2
# Solo un rango de frames (para probar)
npx remotion render MiVideo output/preview.mp4 --frames=0-90
El renderizado local usa tu CPU. Un vídeo de 1 minuto en 1080p tarda entre 1 y 5 minutos dependiendo de la complejidad y tu hardware. Puedes aumentar la concurrencia con --concurrency=8 si tienes múltiples cores.
Renderizado en AWS Lambda (céntimos por vídeo)
npm install @remotion/lambda
Lambda distribuye el renderizado en múltiples funciones serverless que trabajan en paralelo. Un vídeo de 1 minuto que tarda 3 minutos localmente puede tardar 15 segundos en Lambda. El coste es mínimo: céntimos por vídeo.
import { renderMediaOnLambda } from "@remotion/lambda/client";
const result = await renderMediaOnLambda({
region: "eu-west-1",
functionName: "remotion-render",
composition: "MiVideo",
serveUrl: "https://mi-bundle.s3.amazonaws.com",
codec: "h264",
inputProps: { titulo: "Video generado en Lambda" },
});
console.log("Video listo:", result.outputUrl);
Renderizado en GitHub Actions (gratis con minutos incluidos)
Para proyectos open-source o con los minutos gratuitos de GitHub, puedes renderizar en CI/CD:
# .github/workflows/render-video.yml
name: Render Video
on:
push:
paths: ["src/**", "public/**"]
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx remotion render MiVideo output/video.mp4
- uses: actions/upload-artifact@v4
with:
name: video
path: output/video.mp4
Cada vez que haces push con cambios en el código del vídeo, GitHub Actions lo renderiza automáticamente y lo guarda como artefacto descargable. Gratuito dentro de los límites del plan free de GitHub (2.000 minutos/mes).
¿Cuál elegir?
Local: desarrollo, pruebas, videos puntuales. Gratis y rápido para iterar.
Lambda: producción a escala. Cuando necesitas renderizar muchos videos rápidamente. Céntimos por vídeo.
GitHub Actions: CI/CD automatizado. Cada push genera el vídeo actualizado. Perfecto para proyectos con actualizaciones frecuentes.
Pipeline de producción real
Vamos a juntar todo en un pipeline que funciona en producción. Este es el flujo que usamos para generar contenido de vídeo de forma automatizada.
Arquitectura del pipeline
Datos (API/JSON/DB)
|
v
[Script Node.js]
|
+----+----+
| |
v v
TTS Template
(audio) (Remotion)
| |
+----+----+
|
v
[Remotion Render]
|
v
MP4/WebM
|
v
[Distribucion]
YouTube / RRSS / Email
Script del pipeline completo
// scripts/pipeline.ts
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
import { generarAudioTTS } from "./tts";
import { obtenerDatos } from "./datos";
import { publicar } from "./distribucion";
async function pipeline() {
// 1. Obtener datos
const datos = await obtenerDatos();
console.log(`Datos obtenidos: ${datos.items.length} elementos`);
// 2. Generar voiceover (si aplica)
const audioPath = await generarAudioTTS(datos.guion);
console.log(`Audio generado: ${audioPath}`);
// 3. Bundlear el proyecto Remotion
const bundled = await bundle({
entryPoint: "./src/index.ts",
webpackOverride: (config) => config,
});
// 4. Preparar composicion
const composition = await selectComposition({
serveUrl: bundled,
id: "VideoSemanal",
inputProps: {
...datos,
audioPath,
},
});
// 5. Renderizar
const outputPath = `./output/video-${Date.now()}.mp4`;
await renderMedia({
composition,
serveUrl: bundled,
codec: "h264",
outputLocation: outputPath,
inputProps: {
...datos,
audioPath,
},
});
console.log(`Video renderizado: ${outputPath}`);
// 6. Distribuir
await publicar(outputPath, {
titulo: datos.titulo,
descripcion: datos.descripcion,
plataformas: ["youtube", "linkedin", "twitter"],
});
console.log("Video publicado en todas las plataformas");
}
pipeline().catch(console.error);
Este pipeline se puede ejecutar manualmente, con un cron job, o como paso en un workflow de n8n. El punto clave es que cada paso es independiente y testeable por separado.
Estructura de archivos recomendada para producción
mi-video-pipeline/
├── src/
│ ├── Root.tsx # Composiciones registradas
│ ├── components/ # Componentes reutilizables
│ │ ├── Titulo.tsx
│ │ ├── BarChart.tsx
│ │ ├── Subtitulos.tsx
│ │ └── CTA.tsx
│ ├── templates/ # Templates completos
│ │ ├── Infografia.tsx
│ │ ├── SocialClip.tsx
│ │ └── Presentacion.tsx
│ └── schemas/ # Schemas de datos (Zod)
│ └── infografia.ts
├── scripts/
│ ├── pipeline.ts # Pipeline principal
│ ├── batch-render.ts # Renderizado batch
│ ├── tts.ts # Generacion de audio
│ └── distribucion.ts # Publicacion en plataformas
├── data/ # Datos de entrada
│ └── clientes.json
├── output/ # Videos generados (gitignored)
├── public/ # Assets estaticos
│ ├── fonts/
│ ├── images/
│ └── audio/
├── remotion.config.ts
├── package.json
└── tsconfig.json
9 errores que vas a cometer (y cómo evitarlos)
Después de generar cientos de videos con Remotion, estos son los errores que hemos cometido (y que tú puedes evitar).
1. No usar tabular-nums para números
Cuando animas un contador (1, 2, 3... 100), los dígitos "saltan" porque cada número tiene un ancho diferente. La solución es una línea de CSS:
style={{ fontVariantNumeric: "tabular-nums" }}
2. Olvidar el extrapolateRight: "clamp"
Sin clamp, las animaciones continúan más allá del rango definido. Tu opacidad pasa de 1 a 2 a 3... Tu elemento se hace enorme o desaparece. Pon clamp siempre que uses interpolate.
3. Importar imágenes pesadas sin optimizar
Remotion renderiza cada frame como una imagen. Si tu componente carga una imagen de 5 MB, la carga en cada frame. Optimiza las imágenes antes (WebP, 1920px max) o usa <Img> de Remotion que tiene caché interno.
import { Img } from "remotion";
// Mejor que <img> nativo
<Img src={staticFile("hero.webp")} style={{ width: "100%" }} />
4. Animar demasiadas propiedades a la vez
Más animaciones no es mejor. Si todo se mueve, nada destaca. Regla práctica: máximo 2 propiedades animadas por elemento (opacidad + posición, o escala + rotación). El resto, estático.
5. No probar en resolución final
Algo que se ve bien a 720p puede verse borroso a 1080p. Prueba siempre en la resolución final antes de renderizar el vídeo completo. En el Remotion Studio puedes cambiar el zoom pero la resolución real se mantiene.
6. Ignorar la duración del audio
Si tu voiceover dura 47 segundos y tu vídeo dura 45, se corta. Siempre calcula la duración del audio primero y ajusta los frames del vídeo en consecuencia:
import { getAudioDurationInSeconds } from "@remotion/media-utils";
const duracion = await getAudioDurationInSeconds(staticFile("voiceover.mp3"));
const frames = Math.ceil(duracion * 30); // 30 fps
7. Hardcodear colores y fuentes
Si cada componente tiene sus propios colores hardcodeados, cambiar el branding es una pesadilla. Define un theme y pásalo como prop o contexto:
const theme = {
bg: "#0f0f18",
text: "#ffffff",
accent: "#ef4444",
font: "Inter, sans-serif",
};
8. No versionar el output
Nombra los archivos de salida con fecha, versión o hash. video.mp4 se sobreescribe. video-2026-08-27-v3.mp4 no. Cuando el cliente dice "prefería la versión anterior", la tienes.
9. Renderizar el vídeo entero para probar un cambio
Si tu vídeo dura 2 minutos y quieres probar cómo se ve la escena del segundo 45, no renderices los 2 minutos. Usa --frames:
# Solo renderizar del segundo 40 al 50 (a 30fps)
npx remotion render MiVideo preview.mp4 --frames=1200-1500
Casos de uso reales
Para que veas que Remotion no es teoría: estos son casos de uso que empresas y creadores usan en producción ahora mismo.
Infografías animadas para redes sociales
Un template de infografía que recibe datos semanales (métricas de negocio, estadísticas de industria, rankings) y genera un vídeo de 30 segundos con gráficos animados. Se pública automáticamente en LinkedIn, Twitter e Instagram. En lugar de que un diseñador cree una imagen estática cada semana, el pipeline genera un vídeo animado que obtiene 3x más engagement.
Videos de bienvenida personalizados
Cuando un nuevo usuario se registra en una plataforma, se genera automáticamente un vídeo de 15 segundos con su nombre, el plan que eligió y un recorrido visual de las funcionalidades. Se envía por email. Las tasas de activación suben porque el usuario siente que la experiencia fue hecha para él.
Clips de changelog para SaaS
Cada vez que se pública una nueva versión del producto, un script lee los release notes de GitHub, genera un vídeo corto mostrando las novedades con capturas animadas y lo sube a YouTube y al blog. Los usuarios prefieren ver un vídeo de 60 segundos a leer un changelog de 500 palabras.
Presentaciones de datos para clientes
Una consultora genera reportes mensuales para 50 clientes. Cada reporte incluye un vídeo de 2 minutos con los KPIs animados del mes, comparativas con el mes anterior y recomendaciones. Antes tardaban 3 días en producir 50 presentaciones. Ahora tarda 20 minutos con el pipeline automatizado.
Series educativas para YouTube
Canales de YouTube faceless (sin presenter a cámara) usan Remotion para generar el contenido visual completo: textos animados, gráficos, transiciones, lower thirds. Combinado con TTS para la voz, un solo creador puede publicar 3 videos semanales sin equipo de producción.
Preguntas frecuentes
¿Es Remotion realmente gratis?
Sí. Es open-source con una licencia que permite uso gratuito para empresas con menos de 150.000 USD de ingresos anuales. Para proyectos personales, educativos y la mayoría de startups es completamente gratis. Solo necesitas licencia de pago si tu empresa supera ese umbral.
¿Necesito saber programar para usar Remotion?
Necesitas conocimientos básicos de React y JavaScript/TypeScript. Si ya sabes hacer componentes React, puedes crear videos con Remotion. Además, con herramientas de IA como Claude Code puedes generar el código sin escribirlo tú directamente. El Módulo 03 de IAcademy (gratuito) te enseña los fundamentos necesarios.
¿Qué diferencia hay entre Remotion y herramientas como Canva o Gamma?
Canva y Gamma son herramientas visuales de arrastrar y soltar. Remotion es programático: escribes código que genera vídeo. La ventaja de Remotion es la automatización: puedes generar cientos de videos distintos con datos diferentes sin tocar la interfaz. Canva es mejor para un vídeo puntual; Remotion es mejor para producción a escala.
¿Puedo renderizar videos en la nube gratis?
Puedes renderizar localmente gratis sin límite. Para la nube, Remotion ofrece integración con AWS Lambda (pagas solo el cómputo de Lambda, céntimos por vídeo) y también puedes usar GitHub Actions con minutos gratuitos incluidos en el plan free.
¿Remotion sirve para hacer presentaciones tipo PowerPoint?
Sí. Puedes estructurar composiciones como slides con transiciones usando @remotion/transitions. El resultado es un vídeo MP4 que funciona como presentación animada, mucho más impactante que un PowerPoint estático. Y se puede compartir por cualquier canal sin necesidad de software especial.
¿Cuánto tarda en renderizar un vídeo de 5 minutos?
Depende de la complejidad. Un vídeo de 5 minutos con animaciones CSS y texto tarda entre 2 y 8 minutos en un MacBook con M1/M2. Videos con imágenes pesadas o efectos complejos pueden tardar más. El renderizado en paralelo con Lambda reduce esto a segundos.
¿Puedo usar fuentes personalizadas?
Sí. Coloca los archivos de fuente (.woff2, .ttf) en la carpeta public/fonts/ y cárgalos con @font-face en un CSS global o con el paquete @remotion/google-fonts para fuentes de Google Fonts directamente.
¿Remotion funciona en Windows?
Sí. Remotion funciona en Windows, macOS y Linux. La única diferencia es que en Windows necesitas tener Chrome instalado (en macOS y Linux lo detecta o instala automáticamente). El rendimiento de renderizado es similar en todas las plataformas.
Descarga la guía maestra de Claude (gratis)
Prompts avanzados, workflows y automatización con herramientas como Remotion. PDF directo a tu email.
Empieza gratis con IAcademy
El Módulo 03 cubre automatización, herramientas programáticas y tu primer agente funcional. Sin coste.
Acceder al Módulo 03 gratisCurso completo: 614 módulos de IA aplicada
23 especializaciones por departamento. Dashboard con progreso. Quizzes y skills desbloqueables. Desde 19 EUR.
📚 Aprende más en el curso
Este artículo complementa el Módulo M06: IA para contenido. Incluye vídeo, quiz, flashcards con repaso espaciado y proyecto práctico.