OfficialVídeo e Animaçãogithub.com

remotion-markup

Diretrizes de conteúdo, animação e efeitos para desenvolvimento com Remotion.

O que é remotion-markup?

Este skill fornece as melhores práticas para escrever JSX no Remotion, cobrindo desde regras gerais de estrutura e animação até uso de componentes interativos, mídia e efeitos visuais. Ele enfatiza a preservação das edições do usuário no código, o uso de `useCurrentFrame()` e `interpolate()` para animações em vez de CSS `transition` ou `animation`, e a aplicação de `premountFor` para pré-carregar componentes. O skill também orienta sobre como estruturar cenas com `Interactive.withSchema` para props editáveis no Studio, como posicionar assets na pasta `public/` com `staticFile()`, e como usar componentes de mídia (`<Video>`, `<Audio>`, `<CanvasImage>`, `<AnimatedImage>`) importados de `@remotion/media`. Além disso, fornece exemplos completos de cenas, incluindo um cenário com vídeo de fundo e lower third interativo, e explica como lidar com atrasos, cortes, mapas, destaques de texto, vídeos com múltiplas cenas, composições conectadas, narração, incorporação de vídeo/áudio, cortes, transições, motion blur e efeitos visuais. O skill referencia vários documentos complementares para tópicos avançados e recomenda o uso de efeitos embutidos (`effects`) em componentes que os suportam, ou o encapsulamento em `<HtmlInCanvas>` para elementos DOM comuns.

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

Installed? Explore more Vídeo e Animação skills: steipete/video-frames, steipete/summarize, openclaw/openclaw · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

Documentação

Este é um guia para escrever JSX no Remotion. Se isso não for relevante, carregue as Melhores Práticas do Remotion.

Preservar alterações do usuário

Os usuários podem fazer edições no código fora da conversa.

Se você detectar uma alteração surpreendente feita no meio tempo, não a sobrescreva. Suponha que foi intencional ou peça confirmação.

Regras gerais

Dentro de uma composição ou componente de cena, obtenha fps de useVideoConfig() para todos os cálculos de segundos para quadros, incluindo props de temporização como from, trimBefore, durationInFrames e premountFor. Manter a expressão no nó JSX, como trimBefore={4 * fps}, permite que o Studio edite a temporização e a mantenha correta se a taxa de quadros da composição mudar.

Conduza animações usando useCurrentFrame() e interpolate(). CSS transition ou animation não renderizarão corretamente; eles precisam ser refatorados. Classes de animação do Tailwind não renderizarão corretamente; elas precisam ser refatoradas.

Use Easing.bezier() e Easing.spring() para personalizar a temporização.

Estruture seu JSX de acordo com as Melhores Práticas de Interatividade do Remotion. Prefira Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'}) para cenas com props editáveis. O JSX interno pode retornar um fragmento; o wrapper lida com o layout e estilos de instância. Elementos dimensionados, como barras de título, podem manter o layout padrão e repassar style para sua própria raiz. Registre cenas reutilizáveis como composições conectadas. Coloque a temporização diretamente em componentes que a suportam; evite wrappers <Sequence> redundantes. Dê a cada componente com temporização que suporte premountFor um segundo de pré-montagem: premountFor={fps}, onde fps vem de useVideoConfig(). Aplique isso a mídia, componentes interativos, <Sequence>, <TransitionSeries.Sequence> e <TransitionSeries.Overlay>, incluindo componentes com temporização aninhados dentro de cenas. Pré-monte o item da linha do tempo pai também quando um item aninhado precisar ser montado antes do pai começar. Um componente sem premountFor, como <TransitionSeries.Transition>, não precisa de substituto.

O Studio edita o nó de origem JSX que criou um item. Crie cada registro de composição, clipe, cena, camada e sequência que deve ser editável independentemente como seu próprio nó JSX, com suas props editáveis inline. Loops programáticos são adequados quando as instâncias geradas são intencionalmente controladas como um modelo de origem único, não quando os usuários precisam editar as instâncias separadamente.

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>
  );
};

Mantenha a chamada interpolate() inline na prop style. Use as propriedades CSS scale, translate, rotate em vez de transform.

// 👍 Keyframes editáveis inline e atalhos de transformação
style={{
  scale: interpolate(frame, [0, 100], [0, 1], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
    output: 'perceptual-scale' // Para animações de `scale`, use "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 não inline e strings de transformação tornam-se mais difíceis de editar no Studio
const scale = interpolate(frame, [0, 100], [0, 1]);

style={{
  transform: `scale(${scale})`,
}}

Assets

Coloque os assets na pasta public/ na raiz do seu projeto. Use staticFile() para referenciar arquivos da pasta public/.

Componentes de mídia

Adicione vídeo e áudio usando <Video> e <Audio> de @remotion/media. Adicione imagens usando o componente <CanvasImage>. Adicione GIFs animados, APNG, WebP ou AVIF usando <AnimatedImage>. Use @remotion/gif se não estiver usando Chrome. Use staticFile() para arquivos em public/ ou passe uma URL remota diretamente:

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} />
    </>
  );
};

Se a composição for principalmente uma linha do tempo de clipes de vídeo ou áudio, leia video-editing.md antes de escolher sua estrutura de origem.

Exemplo de cena

Um vídeo de fundo com uma barra de título inferior. A barra de título inferior é um componente interativo com sua própria linha do tempo, registrado como uma composição conectada. Seu texto é passado como children e accentColor é uma prop editável. A animação de entrada é keyframed inline no local de chamada.

// 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: "Accent color",
  },
} 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",
        }}
      />
    </>
  );
};

Atraso e corte

Coloque a temporização diretamente em componentes que a suportam. Consulte Timing props para as props suportadas, exemplos e ordem de operações.

Mapas

Consulte Remotion Maps se desejar incluir mapas no vídeo.

Destaques e anotações de texto

Consulte text-highlights.md para destaques de texto (marcadores de destaque), círculos, sublinhados, tachados, texto riscado, caixas.

Vídeos com múltiplas cenas

Consulte multi-scene-video.md se estiver planejando fazer um vídeo com várias cenas subsequentes.

Composições conectadas

Quando uma cena ou grupo de camadas merece sua própria linha do tempo editável, siga connected-compositions.md. Prefira essa estrutura para cenas substanciais em um vídeo com múltiplas cenas.

Ação de pré-composição

Para uma solicitação do Studio como Pre-compose Ambient glow (src/BarChart.tsx:134), encontre o JSX da sequência selecionada no local fornecido. Crie uma composição conectada, seguindo connected-compositions.md: extraia o JSX para um componente nomeado, de preferência torne-o interativo com Interactive.withSchema({wrapInSequence: true}), e registre a mesma referência de componente exportada com um <Composition> único na raiz. Renderize o componente interativo diretamente com suas props de temporização, ou como o único filho de uma sequência quando esse wrapper tiver um propósito. Se o nó selecionado já for uma sequência, mantenha suas props e extraia seus filhos. O registro precisa de dimensões, fps, duração e defaultProps equivalentes ao uso pai. Uma extração de componente sem uma composição registrada não completa uma solicitação de pré-composição.

Carregue estilos herdados como fontFamily e carregamento de fontes para o componente extraído; consulte independência do pai.

Narração

Consulte voiceover.md para adicionar uma narração gerada por IA a composições Remotion usando ElevenLabs TTS.

Incorporação de vídeos

Consulte embedding-videos.md para conhecimento avançado sobre incorporação de vídeos - corte, volume, velocidade, loop, pitch.

Incorporação de áudio

Consulte audio.md para recursos avançados de áudio como corte, volume, velocidade, pitch.

Corte (cropping)

Consulte cropping.md se precisar cortar o retângulo visível de um componente.

Transições

Consulte transitions.md para padrões de transição de cena.

Motion blur

Ao adicionar motion blur ou um rastro de movimento, leia motion-blur.md para a abordagem preferida de HTML em canvas, requisitos de preview e alternativas.

Efeitos visuais e de pixel

Ao adicionar um efeito visual, primeiro identifique o elemento ou grupo que ele deve afetar. Se o componente alvo suportar effects e um efeito embutido abaixo corresponder à solicitação, prefira esse efeito a uma aproximação CSS. Por exemplo, aplique vignette() diretamente à prop effects de um <Video> quando a vinheta deve afetar esse vídeo.

Estes componentes aceitam effects diretamente:

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>

Elementos HTML comuns, wrappers DOM <Interactive.*>, <AbsoluteFill> e <Sequence> não aceitam effects diretamente. Para aplicar efeitos ao seu conteúdo, envolva-os em <HtmlInCanvas> e coloque a prop effects no wrapper.

Para outros elementos, prefira HTML e CSS regulares onde adequado. Considere envolver um grupo em <HtmlInCanvas> quando o pós-processamento de todo o grupo for apropriado e o ambiente suportá-lo.

Leia effects.md antes de aplicar um efeito para imports, parâmetros e configuração. Ele também cobre efeitos personalizados reutilizáveis com createEffect() quando nenhum efeito embutido corresponder.

Efeitos disponíveis

Efeitos embutidos de @remotion/effects:

  • Cor e tom: brightness(), colorCorrection(), colorKey(), contrast(), duotone(), exposure(), grayscale(), hue(), invert(), levels(), linearGradient(), linearGradientTint(), lut(), saturation(), shadowsHighlights(), thermalVision(), tint(), vibrance(), whiteBalance().
  • Blur e rastros: blur(), lightTrail(), linearProgressiveBlur(), radialProgressiveBlur(), regionBlur(), transparentizeLastTrailFrames(), vignette().
  • Distorção e deslocamento: bitFlop(), chromaticAberration(), displacementMap(), imageDistortion(), inflation(), lensDistortion(), lightLeaks(), mirror(), pixelation(), ring(), scanlines(), shake(), wave().
  • Sobreposições e bordas: edge(), glitch(), glow(), outline(), stroke().
  • Mascaramento e composição: clipRegion(), fillRegion(), imageOverlay(), lumaKey(), noise(), pictureInPicture(), remapRegion(), replaceColor(), shadow(), solidOverlay(), textOverlay().
  • Outros: colorSpaceConversion(), custom(), drop(), fillToAspectRatio(), master().

Consulte efeitos de transição para efeitos que envolvem transições entre cenas.

Individual skills in this repo

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

Habilidades Relacionadas