OfficialVideo y animacióngithub.com

remotion-markup

Guía de mejores prácticas para contenido, animaciones y efectos en React Markup con Remotion.

¿Qué es remotion-markup?

Este skill proporciona pautas detalladas para escribir marcado React optimizado para Remotion, enfocándose en la creación de animaciones, contenido y efectos visuales de alto rendimiento. Explica cómo usar hooks como `useCurrentFrame()` e `interpolate()` en lugar de transiciones CSS, y cómo estructurar componentes interactivos con `Interactive.withSchema()` para permitir la edición en el estudio de Remotion. También cubre el manejo correcto de activos multimedia (video, audio, imágenes), la pre-montación de componentes con `premountFor`, y la aplicación de efectos visuales como viñetas, desenfoque y corrección de color a componentes específicos. Es útil para desarrolladores que crean videos programáticos con Remotion y desean seguir las mejores prácticas de la plataforma para garantizar renderizados correctos y una experiencia de edición fluida.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/remotion-dev/skills/tree/main/skills/remotion-markup

Installed? Explore more Video y animación skills: steipete/video-frames, steipete/summarize, openclaw/openclaw · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Vista previa

Del README del skill

Documentación

Esta es una guía para escribir marcado React de Remotion. Si esto no es relevante, carga Mejores Prácticas de Remotion en su lugar.

Conservar 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 un componente de composición o escena, obtén fps de useVideoConfig() para todos los cálculos de segundos a fotogramas, incluyendo propiedades de temporización como from, trimBefore, durationInFrames y premountFor. Mantener la expresión en el nodo JSX, como trimBefore={4 * fps}, permite que el Estudio edite la temporización y la mantenga correcta si la velocidad de fotogramas de la composición cambia.

Impulsa las animaciones usando useCurrentFrame() e interpolate(). Las transiciones o animaciones CSS 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 la temporización.

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 propiedades editables. Su marcado interno puede devolver un fragmento; el envoltorio maneja el diseño y los estilos de la instancia. Los elementos dimensionados, como los tercios inferiores, pueden mantener el diseño predeterminado y pasar style a su propia raíz. Registra las escenas reutilizables como composiciones conectadas. Coloca la temporización directamente en los componentes que la soporten; evita envoltorios redundantes <Sequence>. Asigna a cada componente temporizado que soporte premountFor un segundo de pre-montaje: 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. También premonta el elemento de la línea de tiempo padre cuando un elemento anidado necesita montarse antes de que el padre comience. Un componente sin premountFor, como <TransitionSeries.Transition>, no necesita sustituto.

El Estudio 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 propiedades 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 interpolate() en línea dentro de la propiedad 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}),
  }),
}}

// 👎 Los valores fuera de línea y las cadenas de transformación son más difíciles de editar en el Estudio
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, APNG, WebP o imágenes AVIF usando <AnimatedImage>, usa @remotion/gif si no usas 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 propiedad editable. La aparición gradual está animada en el lugar de la 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",
        }}
      />
    </>
  );
};

Retardo, recorte

Coloca la temporización directamente en los componentes que la soporten. Consulta Propiedades de temporización para las propiedades soportadas, ejemplos y orden de operaciones.

Mapas

Consulta Mapas de Remotion si deseas incluir mapas en el video.

Resaltados y anotaciones de texto

Consulta resaltados-de-texto.md para resaltados de texto (marcadores de resaltado), círculos, subrayados, tachados, texto tachado, recuadros.

Videos de múltiples escenas

Consulta video-de-multiples-escenas.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-composición

Para una solicitud del Estudio como Pre-componer Resplandor ambiente (src/BarChart.tsx:134), encuentra el marcado de la secuencia seleccionada en la ubicación dada. Crea una composición conectada, siguiendo composiciones-conectadas.md: extrae el marcado en un componente nombrado, preferiblemente hazlo interactivo con Interactive.withSchema({wrapInSequence: true}), y registra la misma referencia de componente exportada con una <Composition> única en la raíz. Renderiza el componente interactivo directamente con sus propiedades de temporización, o como el único hijo de una secuencia cuando ese envoltorio tenga un propósito. Si el nodo seleccionado ya es una secuencia, mantén sus propiedades 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 incrustacion-de-videos.md para conocimiento avanzado sobre incrustación de videos: recorte, volumen, velocidad, bucle, tono.

Incrustación de audio

Consulta audio.md para funciones 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 conocer 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 sobre el que debería actuar. 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 propiedad effects de un <Video> cuando la viñeta deba afectar a ese video.

Estos componentes aceptan effects directamente:

Importar deComponentes
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 envoltorios DOM <Interactive.*>, <AbsoluteFill> y <Sequence> no aceptan effects directamente. Para aplicar efectos a su contenido, envuélvelos en <HtmlInCanvas> y coloca la propiedad effects en el envoltorio.

Para otros elementos, prefiere HTML y CSS regulares cuando sea adecuado. Considera envolver un grupo en <HtmlInCanvas> cuando el post-procesamiento 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(), trail(), vignette(), wind().
  • Dispersión y distorsión: circle(), curl(), displacementMap(), fadeToColor(), hexagonalPixelate(), julia(), noise(), pixelate(), posterize(), selectiveColorBlur(), solidColor(), wave().
  • Arte y efectos especiales: chromaKey(), crt(), dots(), edgeWork(), emboss(), glitch(), glow(), kaleidoscope(), mirror(), oil(), outline(), rembrandt(), sepia(), sketch(), toon(), transparent(), vignetteBlur().

Consulta efectos.md para más detalles sobre estos efectos.

Individual skills in this repo

This repo contains 19 individual skills — each has its own dedicated page.

Skills relacionados