Ao escrever a marcação Remotion de uma maneira específica, o Remotion Studio consegue reconhecer a estrutura do código e torná-lo interativo:
- Permitindo que itens sejam selecionados clicando neles
- Permitindo arrastar e soltar, redimensionar e girar
- Editando os estilos CSS
- Tornando valores de keyframes e easing editáveis
Se a marcação for muito complexa para o Studio tornar interativa, os valores ficarão acinzentados.
Prefira componentes interativos com suas próprias timelines
Construa novas composições com Track, composições conectadas e Interactive.create().
Defina layout explicitamente como 'absolute-fill' para cenas ou 'none' para elementos limitados. Registre os mesmos componentes exportados de cena e elemento reutilizável com Composition.
Comece com o exemplo completo de Track + composições conectadas. Ele inclui o elemento, cena, timeline pai e registros raiz.
import {Track, useVideoConfig} from 'remotion';
import {Chapter} from './Chapter';
export const MyVideo = () => {
const {fps} = useVideoConfig();
return (
<Track name="Chapters">
<Chapter
name="Opening"
durationInFrames={3 * fps}
title="Introduction"
/>
<Chapter
name="Feature"
from={3 * fps}
durationInFrames={4 * fps}
title="New features"
/>
</Track>
);
};
Coloque estilos de fundo e alinhamento em cada instância de cena, como mostrado no exemplo completo. Mantenha contêineres apenas de layout como HTML simples.
Escolha campos de esquema
Cada chave no esquema é uma prop que o Studio pode ler e editar no local de chamada.
Props que não estão no esquema ainda funcionam, mas não são editáveis no Studio.
As chaves podem usar notação de ponto, como style.color.
| Tipo | Uso para | Pode ter keyframe |
|---|---|---|
string | Strings, como título, prompt ou trecho de código | Não |
number | Números, com opcionais min, max, step, integer | Sim |
boolean | Interruptores liga/desliga | Sim (hold) |
color | Strings de cor CSS | Sim |
enum | Uma escolha entre variants, cada um com seu próprio esquema aninhado | Opt-in (hold) |
array | Listas de números, cores, enums e mais | Não |
asset | Fontes de mídia, com opcional assetType | Não |
font-family | Família de fonte CSS | Não |
font-weight | Peso da fonte | Sim |
translate, scale, rotation-css, rotation-degrees, transform-origin | Transformações | Sim |
uv-coordinate | Um ponto normalizado [x, y] no elemento | Sim |
svg-path | Dados de caminho SVG | Sim |
remotion-captions | Dados Caption[] | Não |
hidden | Um valor mantido fora dos controles | — |
Cada campo precisa de um default e deve ter um description, que o Studio mostra como rótulo.
Defina keyframable: false para mostrar um controle estático.
Exponha conteúdo e aparência por instância, como o texto e uma cor de destaque.
Não adicione campos para style.translate, style.scale, style.rotate, style.transformOrigin e style.opacity: o Interactive.create() os adiciona automaticamente.
Para tornar as propriedades CSS da raiz editáveis por instância, espalhe os fragmentos de esquema embutidos:
const cardSchema = {
...Interactive.textSchema, // style.color, style.fontSize, style.fontWeight, ...
...Interactive.backgroundSchema, // style.backgroundColor
...Interactive.borderRadiusSchema, // style.borderRadius, ...
} as const satisfies InteractivitySchema;
Também disponíveis: Interactive.borderSchema e Interactive.captionsSchema para componentes que aceitam legendas.
Para componentes que aceitam filhos React.ReactNode, adicione ...Interactive.childrenSchema.
Ele fornece controles para o conteúdo dos filhos e pode evoluir para suportar conteúdo mais rico.
Atualmente, usa um campo string chamado "Text" com valor padrão ''.
Se um componente exigir filhos apenas de string, declare um campo children explícito com type: 'string'.
Interactive.textSchema controla estilos de tipografia; childrenSchema controla o conteúdo.
O fragmento children não está incluído em baseSchema nem adicionado automaticamente a componentes personalizados.
Marcação aninhada e filhos calculados são atualmente somente leitura.
text-content é um alias obsoleto para o tipo de campo string.
Consulte InteractivitySchema para todas as opções.
Registre componentes reutilizáveis como composições conectadas
Registre cenas e elementos reutilizáveis como composições independentes. O Studio chama estas composições conectadas: elas podem ser abertas em sua própria timeline enquanto compartilham a mesma implementação do componente com o vídeo pai.
Defina estilos necessários e carregue fontes dentro do componente para que funcione sem seu pai. Consulte independência do pai.
Registre a mesma referência de componente exportada que o pai renderiza. Para o
exemplo acima, use component={Chapter}, não ChapterInner ou um wrapper inline.
Interactive.create() fornece a sequência, portanto nenhum <Sequence> extra é necessário para a conexão.
import {Composition} from 'remotion';
import {Chapter} from './Chapter';
export const RemotionRoot = () => (
<Composition
id="Chapter"
component={Chapter}
width={1280}
height={720}
fps={30}
durationInFrames={90}
defaultProps={{
title: 'A new perspective',
style: {
backgroundColor: '#111111',
justifyContent: 'center',
alignItems: 'center',
},
}}
/>
);
Escolha um ID único, padrões inline representativos e dimensões, fps e duração adequados para pré-visualizar o componente. Os padrões de registro não copiam automaticamente props de uma instância pai. Consulte composições conectadas para detalhes de registro e extração.
Coloque a temporização diretamente no componente
Evite um <Sequence> separado em torno de um componente que já aceita props de
temporização. Componentes interativos embutidos e componentes personalizados feitos com
Interactive.create() podem receber name, from, durationInFrames,
trimBefore e playbackRate diretamente.
<Chapter
name="Opening scene"
from={30}
durationInFrames={90}
style={{opacity: 0.9}}
title="A new perspective"
/>
Para temporização compartilhada de cena, agrupe o conteúdo em um componente feito com
Interactive.create() e temporize essa instância. Raízes gerenciadas também aceitam
width e height para useVideoConfig().
Use <Track> para colocar itens na mesma linha da timeline do Studio.
Use <TransitionSeries> quando as cenas são sequenciais.
Dê a cada item editável independente seu próprio nó JSX
O Studio edita o nó fonte JSX que criou um item. Se vários itens de tempo de execução vierem do mesmo nó JSX, eles compartilham um único alvo de edição de fonte.
Para cada registro de composição, clipe, cena, camada ou sequência que deve ser
editável por si só, escreva um nó JSX separado e mantenha suas props editáveis
nesse nó. Isso se aplica a <Composition>, <Still>, componentes de mídia
embutidos, <Sequence>, <TransitionSeries.Sequence>
e componentes personalizados.
Por exemplo, crie uma timeline editável assim:
import { Track } from "remotion";
<Track name="Scenes">
<Introduction name="Introduction" durationInFrames={90} />
<Demo name="Demo" from={90} durationInFrames={150} />
</Track>
Um .map() ou outro loop programático criaria vários itens de tempo de execução
a partir de um nó fonte JSX. Isso é apropriado para saída repetida que é
intencionalmente controlada como um modelo, como barras de visualização ou
partículas. Não é apropriado quando as instâncias precisam de IDs ou
nomes, props, metadados, temporização, ordenação, exclusão ou duplicação independentes no
Studio.
Torne um elemento HTML interativo usando Interactive
Todo elemento HTML e SVG (exceto <Img>, que já é interativo) como <div> pode se tornar interativo usando Interactive:
<Interactive.Div
name="Greeting card"
style={{fontSize: 80, padding: 24}}
>
Hello
</Interactive.Div>
Isso permite que estilos e keyframes sejam definidos no Studio. Seja sensato; se um componente tiver muitos elementos, a timeline pode ficar confusa.
Prefira texto inline
Se o texto é fixo e usado apenas uma vez, escreva-o diretamente dentro do elemento interativo em vez de extraí-lo para uma constante.
// 👍 Cópia fixa permanece editável
<Interactive.Div name="Title">
Remotion Best Practices
</Interactive.Div>
Use uma prop ou variável apenas quando o texto for dinâmico ou reutilizado.
Dê aos elementos interativos um nome descritivo
Adicione uma prop name aos elementos para torná-los facilmente identificáveis.
Evite nomes calculados; codifique-os manualmente.
<>
<Interactive.Div name="Hero title" style={{fontSize: 80}}>
Launch day
</Interactive.Div>
<Img name="Avatar" src="https://remotion.media/image.jpeg" />
<Video name="Background" src="https://remotion.media/video.mp4" />
<Interactive.Div name="Title">
Launch day
</Interactive.Div>
</>
Mantenha todos os estilos CSS inline
A melhor maneira é simplesmente passar um objeto simples para style - sem referência a constantes, sem espalhamento de objetos, sem matemática.
<Interactive.Div
style={{
fontSize: 80,
color: 'red',
}}
>
Hello World!
</Interactive.Div>
const baseStyle = useMemo(() => {
return {
fontSize: 12 // ❌ Estilos não inline não são suportados
}
}, []);
<Interactive.Div
style={{
...baseStyle, // ❌ Espalhamento não é suportado
color: RED, // ❌ Referência a constantes não é suportada
scale: frame * 10 // ❌ Matemática não é suportada
}}
>
Hello World!
</Interactive.Div>
Anime usando interpolate()
Escreva animações como chamadas interpolate() inline na propriedade que muda.
O intervalo de saída, easing, extrapolação e a propriedade output devem usar valores codificados.
O intervalo de entrada pode adicionalmente usar durationInFrames, fps, width e height desestruturados diretamente de useVideoConfig(). Identificadores simples como durationInFrames, multiplicação por um número como 2 * fps ou fps * 2, e subtração de um número como durationInFrames - 1 são suportados.
const {fps, durationInFrames} = useVideoConfig();
// 👍 Valores inline podem ser padronizados e ter keyframe
<Interactive.Div
name="Product card"
style={{
color: 'white',
fontSize: 80,
scale: interpolate(frame, [0, fps], [0, 1], {
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale',
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp'
}),
rotate: interpolate(frame, [0, 1 * fps], ['0deg', '20deg'], {
easing: Easing.spring({damping: 200}),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp'
}),
translate: interpolate(
frame,
[durationInFrames - 30, durationInFrames],
['0px 0px', '0px 120px'],
{
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale',
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp'
}
),
}}
/>
const translateY = interpolate(frame, [0, 30], [0, 120]); // ❌ A matemática deve estar diretamente na marcação
<Interactive.Div
name="Product card"
style={{
translate: translateY, // ❌ Apenas chamadas inline interpolate() são suportadas,
rotate: interpolate(frame, [start, start + 10], [0, Math.PI]), // ❌ Não pode usar matemática com variáveis arbitrárias, não pode usar constantes
scale: interpolate(anyVariable, [0, 30], [0, 1]) // ❌ Só pode interpretar a variável `frame`.
}}
/>
Mantenha caminhos SVG editáveis com Interactive.Path
Use <Interactive.Path> de remotion em vez de <path> dentro de um SVG para tornar o caminho visualmente editável.
Instale @remotion/paths para interpolação de caminhos e keyframes de caminho no Studio:
bunx remotion add @remotion/paths
Se a geometria for destinada a ser estática, coloque a string do caminho diretamente na prop d. Não a extraia para uma constante.
import {Interactive} from 'remotion';
<Interactive.Svg width={300} height={300} viewBox="0 0 300 300">
<Interactive.Path
name="Triangle"
d="M 40 40 L 260 40 L 150 260 Z"
fill="#0b84f3"
/>
</Interactive.Svg>
Morph caminhos usando inline
… [truncado para tradução]
