Creación de videos con Claude Code y Remotion
Claude Code con la habilidad de Remotion es un flujo de trabajo para generar video a partir de indicaciones en lenguaje natural: instala la habilidad, genera el andamiaje de un proyecto Remotion, describe el video en inglés sencillo y deja que Claude escriba React con precisión de fotograma que se renderiza a MP4. Ese es el ciclo completo. La fricción nunca está en la indicación — está en comprender suficientemente bien el código que Claude devuelve para corregirlo cuando el resultado renderizado se desvía de lo que pediste. Este artículo recorre un ejemplo orientado al desarrollador de principio a fin, y luego te muestra cómo leer el modelo mental de Remotion para que puedas diagnosticar un render roto desde la vista previa de Studio en lugar de reescribir indicaciones a ciegas.
Puntos clave
- Remotion es un framework de React que renderiza video tratando cada fotograma como una función pura de un número de fotograma, accesible mediante
useCurrentFrame(), y captura esa salida para producir un MP4. - A 30fps, un video de 15 segundos tiene 450 fotogramas; cada animación es un mapeo del número de fotograma a un valor CSS, sin ningún editor de línea de tiempo involucrado.
- El comando de instalación ha aparecido en varias formas en distintos tutoriales — verifica el actual en
remotion.dev/docs/ai/claude-codeantes de ejecutarlo, ya que las herramientas de habilidades han estado en constante cambio. - Cuando las animaciones se disparan simultáneamente en la vista previa, la causa casi siempre son los desplazamientos
fromfaltantes en los componentes<Sequence>, que por defecto comienzan en el fotograma 0. - Remotion renderiza lanzando Chromium en modo headless y capturando cada fotograma, razón por la cual una composición de 30 segundos a 30fps requiere 900 capturas de pantalla y por qué existe Remotion Lambda para pipelines de producción.
En qué consiste este stack
Remotion es un framework de React de código abierto para crear videos de forma programática: defines escenas como componentes de React, controlas el tiempo con números de fotograma y renderizas la salida como MP4, WebM o GIF — sin editor de línea de tiempo, sin arrastrar y soltar. La habilidad de Remotion para Claude Code es un paquete de reglas que enseña al agente la superficie de API de Remotion — composiciones, secuencias, interpolate(), spring(), configuración de render — para que genere cálculos de fotograma correctos en lugar de adivinar. No es un plugin que se ejecuta en tiempo de render; es contexto inyectado en Claude para que el código que escribe compile y anime tal como lo describiste.
¿Cuál es el modelo mental de Remotion?
En Remotion, tu video es una función pura de un número de fotograma. Una composición es un componente de React con una duración fija en fotogramas. A 30fps, un video de 15 segundos tiene 450 fotogramas, y cada animación se expresa como un mapeo del fotograma actual a un valor CSS — opacidad, transformación, color. No hay línea de tiempo; solo hay matemáticas.
Cuatro primitivas sostienen todo el modelo, todas documentadas en los fundamentos de Remotion:
useCurrentFrame()devuelve el fotograma que se está renderizando en ese momento. Tu componente se vuelve a ejecutar para cada fotograma.fpsydurationresiden en<Composition>. Según la documentación de composiciones, allí definesdurationInFrames,fps,widthyheight.<Sequence>desplaza el tiempo. Un hijo envuelto en<Sequence from={90}>ve el fotograma 0 cuando el fotograma global es 90, que es la forma de escalonar escenas.interpolate()mapea un rango de fotogramas a un rango de valores.
Cálculos de fotogramas que usarás constantemente:
| Duración | Fotogramas a 30fps |
|---|---|
| 5s | 150 |
| 10s | 300 |
| 15s | 450 |
| 30s | 900 |
| 60s | 1800 |
Una vez que interiorices “fotograma de entrada, valor CSS de salida”, el código generado deja de parecer magia.
Requisitos previos e instalación
Discover how at OpenReplay.com.
Necesitas Node.js (verifica el requisito de versión en la página de inicio de Remotion antes de instalar) y Claude Code, el agente de codificación en terminal de Anthropic. Claude Code funciona con una suscripción a Claude o con facturación por API — confirma los requisitos de acceso actuales en la documentación de Claude Code de Anthropic, ya que la disponibilidad de planes cambia.
Ahora la parte que todo tutorial omite apresuradamente. El comando de instalación de la habilidad de Remotion ha aparecido al menos en tres formas distintas en publicaciones recientes (npx @anthropic-ai/skills add remotion, npx skills add remotion, npx skills add remotion-dev/skills). El empaquetado de habilidades ha estado evolucionando, así que no confíes en un comando copiado. Abre la página canónica de habilidades — remotion.dev/docs/ai/skills — y ejecuta lo que figure actualmente. Trata esa página como la única fuente de verdad hasta que el ecosistema se estabilice.
Primero verifica que Claude Code esté en tu PATH:
claude --version
Luego instala la habilidad usando el comando de la página de documentación oficial y confirma que se instaló correctamente preguntándole a Claude dentro de un proyecto: “Do you have the Remotion skill loaded?”
Un ejemplo práctico: un clip de presentación de funcionalidades de 15 segundos
Los casos de uso para desarrolladores más potentes de este stack son recursos que regeneras a partir de datos o de forma programada: un clip de registro de cambios construido desde CHANGELOG.md, un diagrama de arquitectura animado que refleja el sistema actual, o una presentación de funcionalidades del producto que se re-renderiza en cada versión. Construiremos la presentación de funcionalidades.
Paso 1 — Andamiaje
El comando de andamiaje está documentado en la página de inicio de Remotion:
npx create-video@latest feature-reveal
cd feature-reveal
npm install
Crea el proyecto con una plantilla o configuración de TypeScript. El andamiaje te proporciona src/Root.tsx (donde se registran las composiciones) y una composición inicial.
Paso 2 — Indicar a Claude Code
Abre el agente en el proyecto y sé explícito con los cálculos de fotogramas — aquí es donde se origina la mayoría de los resultados incorrectos:
Create a Remotion composition called FeatureReveal.
- 15 seconds at 30fps (450 frames), 1920x1080.
- Dark background (#0d1117).
- A headline "Ship changelogs as video" fades in over frames 0-30,
holds, then fades out over frames 420-450.
- Three feature rows below the headline, each sliding up from 40px
with a spring, staggered: row 1 enters at frame 60, row 2 at 90,
row 3 at 120.
- Register FeatureReveal in Root.tsx with the correct
durationInFrames and fps.
Paso 3 — Leer el código generado
Una generación correcta se ve aproximadamente así. El encabezado usa interpolate(); las filas usan desplazamientos <Sequence from> más spring():
import {
AbsoluteFill,
interpolate,
spring,
Sequence,
useCurrentFrame,
useVideoConfig,
} from "remotion";
const features = ["One prompt", "Re-render per release", "Version-controlled"];
const FeatureRow: React.FC<{ label: string }> = ({ label }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// spring() returns 0→1; we map it to translateY and opacity.
const enter = spring({ frame, fps, config: { damping: 14 } });
const translateY = interpolate(enter, [0, 1], [40, 0]);
return (
<div style={{ opacity: enter, transform: `translateY(${translateY}px)` }}>
{label}
</div>
);
};
export const FeatureReveal: React.FC = () => {
const frame = useCurrentFrame();
// Headline opacity: in by frame 30, hold, out from 420 to 450.
const headlineOpacity = interpolate(
frame,
[0, 30, 420, 450],
[0, 1, 1, 0],
{ extrapolateRight: "clamp" }
);
return (
<AbsoluteFill style={{ backgroundColor: "#0d1117", color: "white" }}>
<h1 style={{ opacity: headlineOpacity, fontSize: 72 }}>
Ship changelogs as video
</h1>
{features.map((label, i) => (
// Each row starts 30 frames after the last via `from`.
<Sequence key={label} from={60 + i * 30}>
<FeatureRow label={label} />
</Sequence>
))}
</AbsoluteFill>
);
};
La línea que vale la pena memorizar es el interpolate() del encabezado. La llamada mapea números de fotograma a opacidad: en el fotograma 0 la opacidad es 0, para el fotograma 30 es 1, se mantiene hasta el fotograma 420 y luego se desvanece a 0 en el fotograma 450. El array de fotogramas y el array de valores deben tener la misma longitud, y { extrapolateRight: "clamp" } evita que el valor continúe más allá del último punto — el nombre de la opción y su comportamiento están documentados en la referencia de interpolate().
El escalonamiento proviene de from={60 + i * 30} en cada <Sequence>. Como cada fila es su propia secuencia, su useCurrentFrame() se reinicia a 0 en su fotograma de inicio, por lo que spring() se dispara desde el punto de entrada de la fila en lugar del inicio del video.
Claude también debe registrar la composición en Root.tsx:
import { Composition } from "remotion";
import { FeatureReveal } from "./FeatureReveal";
export const RemotionRoot: React.FC = () => (
<Composition
id="FeatureReveal"
component={FeatureReveal}
durationInFrames={450}
fps={30}
width={1920}
height={1080}
/>
);
Si durationInFrames y fps aquí no coinciden con los números de fotograma en tu componente, el tiempo se rompe. Esta es la causa más común de “el video tiene la duración incorrecta”.
Paso 4 — Vista previa en Studio
Inicia el Remotion Studio:
npm run dev
Studio se abre en tu navegador (presta atención al puerto que imprime — no siempre es el mismo). Selecciona FeatureReveal, presiona reproducir y arrastra el cabezal de reproducción. Arrastrar hasta un fotograma específico es el movimiento de depuración fundamental: la vista previa te muestra exactamente qué renderiza el fotograma N, para que puedas compararlo con los cálculos de fotograma en tu código.
¿Cómo se diagnostica un render de Remotion que se ve incorrecto?
Diagnostica desde la vista previa de Studio, no desde una lista de errores genéricos. Arrastra hasta el fotograma donde aparece el problema y lee el código que controla ese rango de fotogramas. Tres modos de fallo explican la mayoría de los casos.
Todo se anima a la vez. Cuando las animaciones se disparan simultáneamente en la vista previa, la causa casi siempre son los desplazamientos from faltantes en los componentes <Sequence>: cada escena comienza en el fotograma 0 por defecto a menos que establezcas from={startFrame}. Arrastra hasta el fotograma 0 — si las tres filas ya se están moviendo, las secuencias no están escalonadas. Corrígelo preguntando: “Wrap each feature row in its own <Sequence> with from set to 60, 90, and 120.”
El video tiene la duración incorrecta. Claude genera números de fotograma a partir del fps que indicas. Si no especificas fps, asume un valor predeterminado y puede calcular incorrectamente contra una composición configurada de forma diferente. Arrastra hasta el final del cabezal de reproducción: si tu animación de 450 fotogramas termina en el fotograma 300, el durationInFrames de la composición está establecido en 300. Vuelve a indicar con los números exactos — “15 seconds at 30fps is 450 frames; set durationInFrames={450}” — en lugar de algo vago como “hazlo más largo”.
El movimiento se siente robótico. Un interpolate() lineal sin suavizado se percibe como mecánico. Arrastra a través de una animación de entrada: si se mueve a velocidad constante, no hay suavizado. Cambia a spring() para un movimiento orgánico (devuelve un valor de 0→1 que mapeas sobre una transformación), o pasa una opción easing a interpolate() según la documentación de interpolate. Pregunta: “Use spring() for the row entry instead of a linear interpolate.”
Las repeticiones de sesión de videos de demostración incrustados en páginas de destino revelan frecuentemente un modo de fallo separado — la reproducción automática de un MP4 grande que bloquea el renderizado — pero eso es una preocupación de entrega, no de render.
Renderizar a MP4
Renderiza desde la línea de comandos con npx remotion render, pasando el id de la composición y una ruta de salida:
npx remotion render FeatureReveal out/feature-reveal.mp4
Esta es la realidad que las guías rápidas omiten. Remotion renderiza lanzando Chromium en modo headless, capturando cada fotograma y enviando los fotogramas a través de ffmpeg — la arquitectura se describe en la documentación de renderizado. Una composición de 30 segundos a 30fps significa 900 capturas de pantalla del navegador. Por eso el tiempo de renderizado escala con el número de fotogramas y la complejidad por fotograma, y por qué una composición larga o visualmente pesada puede tardar un tiempo considerable en una laptop en lugar de renderizarse “en menos de un minuto”.
Para pipelines de producción — videos largos, muchas variantes, CI que no puede bloquear un agente de compilación — la ruta en la nube documentada de Remotion es Remotion Lambda, que distribuye los fotogramas entre funciones Lambda paralelas. Lambda vale el costo de configuración una vez que el tiempo de renderizado local se convierte en un cuello de botella o necesitas renderizar de forma programada sin depender de la máquina de un desarrollador. Para un clip corto de 15 segundos de uso único, renderiza localmente y omite Lambda.
Remotion es gratuito para individuos y pequeñas empresas; las empresas más grandes necesitan una licencia — verifica los términos actuales en la página de licencia de Remotion antes de distribuir comercialmente.
¿Cuándo no deberías usar Remotion?
Recurre a Remotion cuando el video esté basado en datos, sea repetible o deba coincidir exactamente con un sistema de diseño — un clip de registro de cambios, un diagrama animado, una presentación de funcionalidades por versión. Recurre a un editor tradicional o a un generador de video con IA cuando el contenido sea de acción en vivo, fotorrealista o una pieza creativa de uso único donde el costo de iteración del re-renderizado supere el beneficio del control basado en código. Recortar errores de una grabación con cámara frontal, aplicar corrección de color a material filmado o producir movimiento orgánico y fotorrealista son trabajos con los que Remotion te dará problemas. La línea divisoria es si la salida se beneficia de ser un programa: si lo vas a renderizar una vez y nunca lo volverás a tocar, el código es una carga, no una ventaja.
El valor de este stack está en el segundo render, no en el primero. Una vez que existe una composición, regenerarla a partir de nuevos datos — un nuevo registro de cambios, una nueva métrica, una nueva versión — es un solo comando. Instala la habilidad desde la página de documentación oficial, construye el ejemplo de presentación de funcionalidades anterior y luego apunta la misma composición a datos que realmente distribuyas.
Preguntas frecuentes
interpolate() mapea un rango de fotogramas a un rango de valores de forma lineal por defecto, por lo que controlas los fotogramas de inicio y fin exactos, como desvanecer la opacidad de 0 a 1 entre los fotogramas 0 y 30. spring() devuelve un valor basado en física de 0 a 1 que se suaviza y se asienta de forma natural, el cual mapeas sobre una transformación u opacidad. Usa interpolate() para tiempos precisos y retenciones; usa spring() para movimiento orgánico que debe sentirse menos mecánico.
La duración está controlada por durationInFrames en la Composition en Root.tsx, no por los valores de animación dentro de tu componente. Si durationInFrames es 300 pero tu animación llega hasta el fotograma 450, el render se detiene en el fotograma 300 y corta el resto. El valor de fps también debe coincidir con los cálculos que usaste: a 30fps, 15 segundos son 450 fotogramas. Establece ambos explícitamente para que los cálculos del componente y la configuración de la composición coincidan.
Puedes describir videos en lenguaje natural y dejar que Claude Code genere el React, pero aún necesitas leer la salida para corregirla cuando el render se desvía de lo que pediste. La habilidad enseña a Claude la API de Remotion para que produzca cálculos de fotograma correctos, pero no elimina la necesidad de entender composiciones, secuencias y números de fotograma al depurar. Conocer el modelo mental de fotograma de entrada, valor CSS de salida es lo que te permite diagnosticar problemas desde la vista previa de Studio.
Remotion Lambda vale el costo de configuración una vez que el tiempo de renderizado local se convierte en un cuello de botella o necesitas renderizar de forma programada sin depender de la máquina de un desarrollador. Como Remotion captura cada fotograma a través de Chromium en modo headless, el tiempo de renderizado escala con el número de fotogramas y la complejidad por fotograma, por lo que los videos largos o muchas variantes bloquean una laptop o un agente de compilación. Lambda distribuye los fotogramas entre funciones paralelas. Para un clip corto de uso único, renderiza localmente y omite Lambda.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.