Remotion: Crea Videos y Presentaciones Gratis con Código

Por David Moya · · 35 min lectura

En este artículo

  1. Qué es Remotion y por qué debería importarte
  2. Remotion vs. las alternativas: tabla honesta
  3. Instalación paso a paso (5 minutos)
  4. Tu primer vídeo en 20 líneas de código
  5. Animaciones que parecen de estudio
  6. Presentaciones animadas (adiós PowerPoint)
  7. 8 templates listos para copiar
  8. Videos con datos dinámicos: el superpoder
  9. Remotion + IA: genera videos con Claude Code
  10. Audio, voiceover y subtítulos
  11. Renderizado: local, Lambda y GitHub Actions
  12. Pipeline de producción real
  13. 9 errores que vas a cometer (y cómo evitarlos)
  14. Casos de uso reales
  15. 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:

Dato real: En IAcademy usamos Remotion para generar las infografías animadas del canal de YouTube, los clips de redes sociales y las presentaciones de los módulos del curso. Un pipeline que antes requería un editor de vídeo dedicado ahora corre en un script de Node.js que se ejecuta solo.

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:

Probablemente no es para ti si:

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 gratis

Remotion 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
* Gratis para empresas con <150K USD ingresos anuales. Licencia empresa desde 500 USD/año.

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

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:

  1. 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.
  2. 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.
  3. <AbsoluteFill> es un div que ocupa todo el canvas del vídeo. Es el equivalente al "fondo" de tu composición. Puedes anidar varios AbsoluteFill para crear capas.

Con estos tres conceptos puedes crear cualquier animación. Todo lo demás (transiciones, secuencias, audio) se construye sobre esta base.

Consejo de experiencia: Resiste la tentación de instalar plugins de animación complejos al principio. Con 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.

Caso real: Un e-commerce que vende cursos online usa este patrón para generar un vídeo de bienvenida personalizado para cada estudiante que se inscribe. El nombre del alumno, el título del curso y la fecha de inicio aparecen animados en el vídeo. Lo que antes requería un editor humano, ahora se genera automáticamente cuando llega el pago por Stripe.

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:

  1. IA genera el guion. Le das un tema y genera el texto del vídeo: título, puntos clave, CTA.
  2. IA genera el código Remotion. Toma el guion y produce los componentes React animados.
  3. Remotion renderiza el vídeo. El código se ejecuta y genera el MP4.
  4. IA genera los subtítulos. Whisper (OpenAI) o similar transcribe el audio si lo hay.
  5. 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.

Ver precios Acceder al portal

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.

Nuestra experiencia: En IAcademy, el pipeline de Remotion genera las infografías semanales del canal de YouTube y los clips promocionales para redes sociales. Un workflow de n8n recoge los datos, genera el guion con IA, produce el audio con TTS, renderiza el vídeo con Remotion, y lo programa para publicación. El tiempo de intervención humana se reduce a 10 minutos de supervisión y aprobació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 gratis

Curso completo: 614 módulos de IA aplicada

23 especializaciones por departamento. Dashboard con progreso. Quizzes y skills desbloqueables. Desde 19 EUR.

Ver precios Acceder al portal

📚 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.

Ir al módulo M06 Repasar con FSRS