Ceci est un guide pour écrire du markup React Remotion. Si cela n'est pas pertinent, chargez plutôt Remotion Best Practices.
Préserver les modifications utilisateur
Les utilisateurs peuvent apporter des modifications au code en dehors de la conversation.
Si vous détectez un changement surprenant effectué entre-temps, ne l'écrasez pas, supposez qu'il était intentionnel ou demandez une confirmation.
Règles générales
À l'intérieur d'un composant de composition ou de scène, obtenez fps de useVideoConfig() pour
tous les calculs secondes-à-trames, y compris les propriétés de timing telles que from,
trimBefore, durationInFrames, et premountFor. Garder l'expression sur
le nœud JSX, comme trimBefore={4 * fps}, permet à Studio de modifier le timing et
le maintient correct si la fréquence d'images de la composition change.
Conduisez les animations en utilisant useCurrentFrame() et interpolate().
Les transition ou animation CSS ne seront pas rendues correctement, elles doivent être refactorisées.
Les classes d'animation Tailwind ne seront pas rendues correctement, elles doivent être refactorisées.
Utilisez Easing.bezier() et Easing.spring() pour personnaliser le timing.
Structurez votre markup selon les meilleures pratiques d'interactivité Remotion.
Préférez Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'})
pour les scènes avec des propriétés modifiables. Leur markup interne peut retourner un fragment ; le
wrapper gère la mise en page et les styles d'instance. Les éléments dimensionnés tels que les tiers inférieurs
peuvent conserver la mise en page par défaut et transmettre style à leur propre racine. Enregistrez
les scènes réutilisables en tant que compositions connectées.
Placez le timing directement sur les composants qui le supportent ; évitez les wrappers <Sequence> redondants.
Donnez à chaque composant temporisé qui supporte premountFor une seconde de pré-montage :
premountFor={fps}, où fps provient de useVideoConfig(). Appliquez ceci aux
médias, composants interactifs, <Sequence>, <TransitionSeries.Sequence>,
et <TransitionSeries.Overlay>, y compris les composants temporisés imbriqués dans les scènes. Pré-montez également l'élément parent de la timeline
lorsqu'un élément imbriqué doit se monter avant que le parent ne commence. Un composant sans
premountFor, tel que <TransitionSeries.Transition>, n'a besoin d'aucun substitut.
Le Studio modifie le nœud source JSX qui a créé un élément. Créez chaque enregistrement de composition, clip, scène, calque et séquence qui doit être modifiable indépendamment comme son propre nœud JSX, avec ses propriétés modifiables en ligne. Les boucles programmatiques sont appropriées lorsque les instances générées sont intentionnellement contrôlées comme un modèle source unique, pas lorsque les utilisateurs ont besoin de modifier les instances séparément.
import { useCurrentFrame, useVideoConfig, Easing, interpolate, Interactive } from "remotion";
export const FadeIn = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
return (
<Interactive.Div
name="Titre"
premountFor={fps}
style={{
opacity: interpolate(frame, [0, 2 * fps], [0, 1], {
extrapolateRight: "clamp",
extrapolateLeft: "clamp",
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
}}
>
Bonjour le monde !
</Interactive.Div>
);
};
Gardez l'appel interpolate() en ligne dans la propriété style.
Utilisez les propriétés CSS scale, translate, rotate plutôt que transform.
// 👍 Images clés modifiables en ligne et raccourcis de transformation
style={{
scale: interpolate(frame, [0, 100], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale' // Pour les animations `scale`, utilisez "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}),
}),
}}
// 👎 Les valeurs non en ligne et les chaînes de transformation deviennent plus difficiles à modifier dans Studio
const scale = interpolate(frame, [0, 100], [0, 1]);
style={{
transform: `scale(${scale})`,
}}
Actifs
Placez les actifs dans le dossier public/ à la racine de votre projet.
Utilisez staticFile() pour référencer des fichiers depuis le dossier public/.
Composants médias
Ajoutez de la vidéo et de l'audio en utilisant <Video> et <Audio> d'@remotion/media.
Ajoutez des images en utilisant le composant <CanvasImage>.
Ajoutez des GIF animés, APNG, WebP ou des images AVIF en utilisant <AnimatedImage>, utilisez @remotion/gif si vous n'utilisez pas Chrome.
Utilisez staticFile() pour les fichiers dans public/ ou transmettez une URL distante directement :
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 composition est principalement une timeline de clips vidéo ou audio, lisez video-editing.md avant de choisir sa structure source.
Exemple de scène
Une vidéo de fond avec un tiers inférieur.
Le tiers inférieur est un composant interactif avec sa propre timeline, enregistré comme composition connectée.
Son texte est passé comme children et accentColor est une propriété modifiable.
La fondu entrant est animé en ligne sur le site d'appel.
// 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="Arrière-plan"
src="https://remotion.media/video.mp4"
premountFor={fps}
objectFit="cover"
style={{
position: "absolute",
width: "100%",
height: "100%",
}}
/>
<LowerThird
name="Tiers inférieur"
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, Designer Produit
</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: "Couleur d'accentuation",
},
} 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, Designer Produit",
accentColor: "#0b84f3",
}}
/>
</>
);
};
Délai, rognage
Mettez le timing directement sur les composants qui le supportent. Voir Propriétés de timing pour les propriétés prises en charge, des exemples et l'ordre des opérations.
Cartes
Consultez Remotion Maps si vous souhaitez inclure des cartes dans la vidéo.
Surlignements et annotations de texte
Voir text-highlights.md pour les surlignements de texte (marqueurs de surbrillance), les cercles, les soulignements, les barrés, le texte rayé, les boîtes.
Vidéos multi-scènes
Voir multi-scene-video.md si vous prévoyez de réaliser une vidéo avec plusieurs scènes consécutives.
Compositions connectées
Lorsqu'une scène ou un groupe de calques mérite sa propre timeline modifiable, suivez connected-compositions.md. Préférez cette structure pour les scènes importantes dans une vidéo multi-scènes.
Action de pré-composition
Pour une demande Studio telle que Pré-composer la lueur ambiante (src/BarChart.tsx:134), trouvez le markup de séquence sélectionné à l'emplacement donné. Créez une composition connectée, en suivant connected-compositions.md : extrayez le markup dans un composant nommé, de préférence rendez-le interactif avec Interactive.withSchema({wrapInSequence: true}), et enregistrez la même référence de composant exportée avec un <Composition> unique dans la racine. Rendez le composant interactif directement avec ses propriétés de timing, ou comme le seul enfant d'une séquence lorsque ce wrapper a un but. Si le nœud sélectionné est déjà une séquence, conservez ses propriétés et extrayez ses enfants. L'enregistrement a besoin des dimensions, fps, durée et defaultProps équivalents à son utilisation parent. Une extraction de composant sans composition enregistrée ne complète pas une demande de pré-composition.
Transportez les styles hérités tels que fontFamily et le chargement de police dans le composant
extrait ; voir indépendance parent.
Voix off
Voir voiceover.md pour ajouter une voix off générée par IA aux compositions Remotion en utilisant ElevenLabs TTS.
Incorporation de vidéos
Voir embedding-videos.md pour des connaissances avancées sur l'incorporation de vidéos - rognage, volume, vitesse, bouclage, hauteur.
Incorporation d'audio
Voir audio.md pour des fonctionnalités audio avancées comme le rognage, le volume, la vitesse, la hauteur.
Recadrage
Voir cropping.md si vous avez besoin de recadrer le rectangle visible d'un composant.
Transitions
Voir transitions.md pour les modèles de transition de scène.
Flou de mouvement
Lors de l'ajout d'un flou de mouvement ou d'une traînée de mouvement, lisez motion-blur.md pour l'approche préférée HTML-dans-canvas, les exigences de prévisualisation et les alternatives.
Effets visuels et pixel
Lors de l'ajout d'un effet visuel, identifiez d'abord l'élément ou le groupe qu'il doit affecter.
Si le composant cible prend en charge effects et qu'un effet intégré ci-dessous correspond à la
demande, préférez cet effet à une approximation CSS. Par exemple, appliquez
vignette() directement à la prop effects d'un <Video> lorsque la vignette doit
affecter cette vidéo.
Ces composants acceptent effects directement :
| Importer de | Composants |
|---|---|
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> |
Les éléments HTML ordinaires, les wrappers DOM <Interactive.*>, <AbsoluteFill> et
<Sequence> n'acceptent pas effects directement. Pour appliquer des effets à leur contenu,
enveloppez-les dans <HtmlInCanvas> et placez la prop effects sur le wrapper.
Pour d'autres éléments, préférez le HTML et le CSS standard lorsque c'est approprié. Envisagez d'envelopper un groupe dans <HtmlInCanvas> lorsque le post-traitement de tout le groupe est approprié et que l'environnement le prend en charge.
Lisez effects.md avant d'appliquer un effet pour les imports, les paramètres
et la configuration. Il couvre également les effets personnalisés réutilisables avec createEffect() lorsqu'aucun
effet intégré ne correspond.
Effets disponibles
Effets intégrés depuis @remotion/effects :
- Couleur et teinte :
brightness(),colorCorrection(),colorKey(),contrast(),duotone(),exposure(),grayscale(),hue(),invert(),levels(),linearGradient(),linearGradientTint(),lut(),saturation(),shadowsHighlights(),thermalVision(),tint(),vibrance(),whiteBalance(). - Flou et traînées :
blur(),lightTrail(),linearProgressiveBlur(),radialProgressiveBlur(),regionBlur