Esta es una guía para escribir marcado React de Remotion. Si esto no es relevante, carga en su lugar las Mejores Prácticas de Remotion.
Preservar los cambios del usuario
Los usuarios pueden hacer ediciones en el código fuera de la conversación.
Si detectas un cambio sorprendente realizado mientras tanto, no lo sobrescribas, asume que fue intencional o pide confirmación.
Reglas generales
Dentro de una composición o componente de escena, obtén fps de useVideoConfig() para todos los cálculos de segundos a fotogramas, incluyendo props de tiempo como from, trimBefore, durationInFrames y premountFor. Mantener la expresión en el nodo JSX, como trimBefore={4 * fps}, permite que Studio edite el tiempo y lo mantenga correcto si la frecuencia de fotogramas de la composición cambia.
Impulsa las animaciones usando useCurrentFrame() e interpolate().
Las transiciones CSS (transition) o animaciones (animation) no se renderizarán correctamente; deben ser refactorizadas.
Las clases de animación de Tailwind no se renderizarán correctamente; deben ser refactorizadas.
Usa Easing.bezier() y Easing.spring() para personalizar el tiempo.
Estructura tu marcado de acuerdo con las Mejores Prácticas de Interactividad de Remotion.
Prefiere Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'}) para escenas con props editables. Su marcado interno puede devolver un fragmento; el wrapper maneja el diseño y los estilos de instancia. Elementos con tamaño, como los tercios inferiores, pueden mantener el diseño predeterminado y pasar style a su propia raíz. Registra escenas reutilizables como composiciones conectadas.
Coloca el tiempo directamente en los componentes que lo soportan; evita wrappers <Sequence> redundantes.
Otorga un segundo de premontaje a cada componente temporizado que soporte premountFor:
premountFor={fps}, donde fps proviene de useVideoConfig(). Aplica esto a medios, componentes interactivos, <Sequence>, <TransitionSeries.Sequence> y <TransitionSeries.Overlay>, incluyendo componentes temporizados anidados dentro de escenas. Premonta también el elemento padre de la línea de tiempo cuando un elemento anidado necesita montarse antes de que el padre comience. Un componente sin premountFor, como <TransitionSeries.Transition>, no necesita sustituto.
Studio edita el nodo fuente JSX que creó un elemento. Crea cada registro de composición, clip, escena, capa y secuencia que deba ser editable de forma independiente como su propio nodo JSX, con sus props editables en línea. Los bucles programáticos son adecuados cuando las instancias generadas se controlan intencionalmente como una plantilla fuente única, no cuando los usuarios necesitan editar las instancias por separado.
import { useCurrentFrame, useVideoConfig, Easing, interpolate, Interactive } from "remotion";
export const FadeIn = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
return (
<Interactive.Div
name="Title"
premountFor={fps}
style={{
opacity: interpolate(frame, [0, 2 * fps], [0, 1], {
extrapolateRight: "clamp",
extrapolateLeft: "clamp",
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
}}
>
Hello World!
</Interactive.Div>
);
};
Mantén la llamada a interpolate() en línea dentro de la prop style.
Usa las propiedades CSS scale, translate, rotate en lugar de transform.
// 👍 Fotogramas clave editables en línea y abreviaturas de transformación
style={{
scale: interpolate(frame, [0, 100], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale' // Para animaciones de `scale`, usa "output: 'perceptual-scale'"
}),
translate: interpolate(frame, [0, 100], ["0px 0px", "100px 100px"], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
}),
rotate: interpolate(frame, [0, 100], ["20deg", "90deg"], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
}),
}}
// 👎 Valores no en línea y cadenas transform se vuelven más difíciles de editar en Studio
const scale = interpolate(frame, [0, 100], [0, 1]);
style={{
transform: `scale(${scale})`,
}}
Activos
Coloca los activos en la carpeta public/ en la raíz de tu proyecto.
Usa staticFile() para hacer referencia a archivos de la carpeta public/.
Componentes multimedia
Agrega video y audio usando <Video> y <Audio> de @remotion/media.
Agrega imágenes usando el componente <CanvasImage>.
Agrega GIFs animados, imágenes APNG, WebP o AVIF usando <AnimatedImage>, usa @remotion/gif si no estás en Chrome.
Usa staticFile() para archivos en public/ o pasa una URL remota directamente:
import { Audio, Video } from "@remotion/media";
import { staticFile, CanvasImage, AnimatedImage, useVideoConfig } from "remotion";
export const MyComposition = () => {
const {fps} = useVideoConfig();
return (
<>
<Video src={staticFile("video.mp4")} premountFor={fps} style={{ opacity: 0.5 }} />
<Audio src={staticFile("audio.mp3")} premountFor={fps} />
<CanvasImage
src={staticFile("logo.png")}
premountFor={fps}
style={{ width: 100, height: 100 }}
/>
<Video src="https://remotion.media/video.mp4" premountFor={fps} />
<AnimatedImage src={staticFile('nyancat.gif')} premountFor={fps} />
</>
);
};
Si la composición es principalmente una línea de tiempo de clips de video o audio, lee video-editing.md antes de elegir su estructura fuente.
Escena de ejemplo
Un video de fondo con un tercio inferior.
El tercio inferior es un componente interactivo con su propia línea de tiempo, registrado como una composición conectada.
Su texto se pasa como children y accentColor es una prop editable.
La aparición gradual está animada con fotogramas clave en línea en el sitio de llamada.
// MyScene.tsx
import { Video } from "@remotion/media";
import { Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
import { LowerThird } from "./LowerThird";
export const MyScene = () => {
const { fps } = useVideoConfig();
const frame = useCurrentFrame();
return (
<>
<Video
name="Background"
src="https://remotion.media/video.mp4"
premountFor={fps}
objectFit="cover"
style={{
position: "absolute",
width: "100%",
height: "100%",
}}
/>
<LowerThird
name="Lower third"
from={1 * fps}
premountFor={fps}
accentColor="#0b84f3"
style={{
opacity: interpolate(frame, [1 * fps, 2 * fps], [0, 1], {
extrapolateRight: "clamp",
extrapolateLeft: "clamp",
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
}}
>
Jane Doe, Product Designer
</LowerThird>
</>
);
};
// LowerThird.tsx
import type React from "react";
import { Interactive, type InteractivitySchema } from "remotion";
type LowerThirdProps = {
readonly children: React.ReactNode;
readonly accentColor: string;
readonly style?: React.CSSProperties;
};
const LowerThirdInner: React.FC<LowerThirdProps> = ({
children,
accentColor,
style,
}) => {
return (
<Interactive.Div
style={{
position: "absolute",
left: 80,
bottom: 80,
display: "flex",
alignItems: "center",
gap: 20,
backgroundColor: "white",
borderRadius: 16,
padding: "20px 32px",
color: "black",
fontFamily: "Helvetica, Arial, sans-serif",
fontSize: 48,
fontWeight: 600,
...style,
}}
>
<div
style={{
width: 8,
alignSelf: "stretch",
borderRadius: 4,
backgroundColor: accentColor,
}}
/>
{children}
</Interactive.Div>
);
};
const lowerThirdSchema = {
...Interactive.childrenSchema,
accentColor: {
type: "color",
default: "#0b84f3",
description: "Color de acento",
},
} as const satisfies InteractivitySchema;
export const LowerThird = Interactive.withSchema({
Component: LowerThirdInner,
componentName: "LowerThird",
schema: lowerThirdSchema,
wrapInSequence: true,
});
import { Composition } from "remotion";
import { LowerThird } from "./LowerThird";
import { MyScene } from "./MyScene";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="MyScene"
component={MyScene}
durationInFrames={60}
fps={30}
width={1280}
height={720}
/>
<Composition
id="LowerThird"
component={LowerThird}
durationInFrames={30}
fps={30}
width={1280}
height={720}
defaultProps={{
children: "Jane Doe, Product Designer",
accentColor: "#0b84f3",
}}
/>
</>
);
};
Retraso, recorte
Coloca el tiempo directamente en los componentes que lo soportan. Consulta Props de tiempo para las props soportadas, ejemplos y orden de operaciones.
Mapas
Consulta Mapas de Remotion si deseas incluir mapas en el video.
Resaltados de texto y anotaciones
Consulta resaltados-de-texto.md para resaltados de texto (marcadores de resaltado), círculos, subrayados, tachados, texto tachado y cuadros.
Videos de múltiples escenas
Consulta video-multi-escena.md si planeas hacer un video con múltiples escenas consecutivas.
Composiciones conectadas
Cuando una escena o grupo de capas merece su propia línea de tiempo editable, sigue composiciones-conectadas.md. Prefiere esta estructura para escenas sustanciales en un video de múltiples escenas.
Acción de pre-componer
Para una solicitud de Studio como Pre-componer Resplandor ambiental (src/BarChart.tsx:134), encuentra el marcado de secuencia seleccionado en la ubicación dada. Crea una composición conectada, siguiendo composiciones-conectadas.md: extrae el marcado en un componente con nombre, preferiblemente hazlo interactivo con Interactive.withSchema({wrapInSequence: true}), y registra la misma referencia de componente exportada con un <Composition> único en la raíz. Renderiza el componente interactivo directamente con sus props de tiempo, o como el único hijo de una secuencia cuando ese wrapper tenga un propósito. Si el nodo seleccionado ya es una secuencia, conserva sus props y extrae sus hijos. El registro necesita dimensiones, fps, duración y defaultProps equivalentes a su uso padre. Una extracción de componente sin una composición registrada no completa una solicitud de pre-composición.
Lleva los estilos heredados como fontFamily y la carga de fuentes al componente extraído; consulta independencia-del-padre.
Voz en off
Consulta voz-en-off.md para agregar una voz en off generada por IA a las composiciones de Remotion usando ElevenLabs TTS.
Incrustación de videos
Consulta incrustación-de-videos.md para conocimiento avanzado sobre incrustación de videos: recorte, volumen, velocidad, bucle, tono.
Incrustación de audio
Consulta audio.md para características avanzadas de audio como recorte, volumen, velocidad, tono.
Recorte
Consulta recorte.md si necesitas recortar el rectángulo visible de un componente.
Transiciones
Consulta transiciones.md para patrones de transición de escenas.
Desenfoque de movimiento
Al agregar desenfoque de movimiento o una estela de movimiento, lee desenfoque-de-movimiento.md para el enfoque preferido de HTML en canvas, requisitos de vista previa y alternativas.
Efectos visuales y de píxeles
Al agregar un efecto visual, primero identifica el elemento o grupo al que debe afectar.
Si el componente objetivo soporta effects y un efecto incorporado a continuación coincide con la solicitud, prefiere ese efecto sobre una aproximación CSS. Por ejemplo, aplica vignette() directamente a la prop effects de un <Video> cuando el viñeteado debe afectar ese video.
Estos componentes aceptan effects directamente:
| Importar desde | Componentes |
|---|---|
remotion | <Img>, <CanvasImage>, <AnimatedImage>, <Solid>, <HtmlInCanvas> |
@remotion/media | <Video> |
@remotion/gif | <Gif> |
@remotion/rive | <RemotionRiveCanvas> |
@remotion/shapes | <Arrow>, <Callout>, <Circle>, <Ellipse>, <Heart>, <Pie>, <Polygon>, <Rect>, <Spark>, <Star>, <Triangle> |
Los elementos HTML ordinarios, los wrappers DOM <Interactive.*>, <AbsoluteFill> y <Sequence> no aceptan effects directamente. Para aplicar efectos a su contenido, envuélvelos en <HtmlInCanvas> y coloca la prop effects en el wrapper.
Para otros elementos, prefiere HTML y CSS regulares cuando sea adecuado. Considera envolver un grupo en <HtmlInCanvas> cuando el posprocesamiento de todo el grupo sea apropiado y el entorno lo soporte.
Lee efectos.md antes de aplicar un efecto para importaciones, parámetros y configuración. También cubre efectos personalizados reutilizables con createEffect() cuando ningún efecto incorporado coincida.
Efectos disponibles
Efectos incorporados de @remotion/effects:
- Color y tono:
brightness(),colorCorrection(),colorKey(),contrast(),duotone(),exposure(),grayscale(),hue(),invert(),levels(),linearGradient(),linearGradientTint(),lut(),saturation(),shadowsHighlights(),thermalVision(),tint(),vibrance(),whiteBalance(). - Desenfoque y estelas:
blur(),lightTrail(),linearProgressiveBlur(),radialProgressiveBlur(), `regionBlur …