Esta é uma orientação para escrever marcação Remotion React. 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 entretanto, não a sobrescreva, assuma que ela 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 propriedades 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.
Dirija animações usando useCurrentFrame() e interpolate().
transition ou animation do CSS 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 sua marcação de acordo com as Melhores Práticas de Interatividade do Remotion.
Prefira Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'}) para cenas com propriedades editáveis. Sua marcação interna 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 encaminhar style para sua própria raiz. Registre cenas reutilizáveis como composições conectadas.
Coloque a temporização diretamente nos componentes que a suportam; evite wrappers <Sequence> redundantes.
Dê a cada componente temporizado 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 temporizados aninhados dentro de cenas. Pré-monte o item da linha do tempo pai também quando um item aninhado precisar montar antes do pai começar. Um componente sem premountFor, como <TransitionSeries.Transition>, não precisa de substituto.
O Studio edita o nó fonte JSX que criou um item. Crie cada registro de composição, clipe, cena, camada e sequência que devem ser editáveis independentemente como seu próprio nó JSX, com suas propriedades editáveis inline. Loops programáticos são adequados quando as instâncias geradas são intencionalmente controladas como um modelo fonte ú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.
// 👍 Quadros-chave inline editáveis e abreviações 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 `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})`,
}}
Ativos
Coloque os ativos 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 imagens 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 fonte.
Exemplo de cena
Um vídeo de fundo com uma barra de título.
A barra de título é um componente interativo com sua própria linha do tempo, registrada como uma composição conectada.
Seu texto é passado como children e accentColor é uma propriedade editável.
O fade-in é animado inline no local da 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: "Cor de destaque",
},
} 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, corte
Coloque a temporização diretamente nos componentes que a suportam. Veja Propriedades de temporização para as props suportadas, exemplos e ordem de operações.
Mapas
Veja Remotion Maps se quiser incluir mapas no vídeo.
Destaques e anotações de texto
Veja text-highlights.md para destaques de texto (marcadores de destaque), círculos, sublinhados, tachados, texto riscado, caixas.
Vídeos com múltiplas cenas
Veja multi-scene-video.md se planeja 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 esta estrutura para cenas substanciais em um vídeo de múltiplas cenas.
Ação de pré-composição
Para uma solicitação do Studio como Pré-compor Brilho ambiente (src/BarChart.tsx:134), encontre a marcação da sequência selecionada no local fornecido. Crie uma composição conectada, seguindo connected-compositions.md: extraia a marcação em um componente nomeado, de preferência torne-o interativo com Interactive.withSchema({wrapInSequence: true}), e registre a mesma referência de componente exportada com uma <Composition> única 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.
Leve estilos herdados como fontFamily e carregamento de fonte para o componente extraído; veja independência do pai.
Narração
Veja voiceover.md para adicionar uma narração gerada por IA a composições Remotion usando ElevenLabs TTS.
Incorporação de vídeos
Veja embedding-videos.md para conhecimento avançado sobre incorporação de vídeos - corte, volume, velocidade, loop, pitch.
Incorporação de áudio
Veja audio.md para recursos avançados de áudio como corte, volume, velocidade, pitch.
Corte de imagem
Veja cropping.md se precisar cortar o retângulo visível de um componente.
Transições
Veja transitions.md para padrões de transição de cena.
Desfoque de movimento
Ao adicionar desfoque de movimento ou um rastro de movimento, leia motion-blur.md para a abordagem preferida 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 interno abaixo corresponder à solicitação, prefira esse efeito em vez de uma aproximação CSS. Por exemplo, aplique vignette() diretamente na prop effects de um <Video> quando o vinheta deve afetar aquele vídeo.
Estes componentes aceitam effects diretamente:
| Importar de | 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> |
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 regular e CSS 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 importações, parâmetros e configuração. Também cobre efeitos personalizados reutilizáveis com createEffect() quando nenhum efeito interno corresponder.
Efeitos disponíveis
Efeitos internos 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(). - Desfoque e rastros:
blur(),lightTrail(),linearProgressiveBlur(),radialProgressiveBlur(),regionBlur(). - Distorção:
displacementMap(),mirror(),pixelate(),pixelateRegion(). - Efeitos de iluminação e brilho:
glow(),shimmer(). - Mascaramento e composição:
matte(),overlay(),remapAlpha(). - Efeitos especiais:
vignette().
Não complique demais a escolha: para um desfoque de fundo, blur() é suficiente. Não alcance linearProgressiveBlur() a menos que uma transição de desfoque progressiva seja explícita.
Consulte a documentação de cada efeito para parâmetros e exemplos.