Ceci est un guide pour l'écriture de balisage React Remotion. Si cela n'est pas pertinent, chargez plutôt les Bonnes Pratiques Remotion.
Préserver les modifications utilisateur
Les utilisateurs peuvent effectuer des modifications dans le 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, récupérez fps avec useVideoConfig() pour
tous les calculs secondes-à-images, y compris les propriétés de timing comme 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.
Animez les animations avec useCurrentFrame() et interpolate().
Les transition ou animation CSS ne s'afficheront pas correctement, elles doivent être refactorisées.
Les classes d'animation Tailwind ne s'afficheront pas correctement, elles doivent être refactorisées.
Utilisez Easing.bezier() et Easing.spring() pour personnaliser le timing.
Structurez votre balisage selon les Bonnes Pratiques d'Interactivité Remotion.
Préférez Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'})
pour les scènes avec des propriétés éditables. Leur balisage interne peut retourner un fragment ; le
wrapper gère la disposition et les styles d'instance. Les éléments dimensionnés comme les tiers inférieurs
peuvent conserver la disposition par défaut et transmettre style à leur propre racine. Enregistrez
les scènes réutilisables comme des 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 cela 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 de la timeline parent
lorsqu'un élément imbriqué doit se monter avant que le parent ne commence. Un composant sans
premountFor, comme <TransitionSeries.Transition>, n'a pas besoin de substitut.
Studio modifie le nœud source JSX qui a créé un élément. Créez chaque enregistrement de composition, clip, scène, couche et séquence qui doit être modifiable indépendamment comme son propre nœud JSX, avec ses propriétés éditables 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 doivent 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 éditables 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})`,
}}
Ressources
Placez les ressources dans le dossier public/ à la racine de votre projet.
Utilisez staticFile() pour référencer les fichiers du dossier public/.
Composants média
Ajoutez la vidéo et l'audio avec <Video> et <Audio> depuis @remotion/media.
Ajoutez les images avec le composant <CanvasImage>.
Ajoutez les GIFs animés, APNG, WebP ou AVIF avec <AnimatedImage>, utilisez @remotion/gif si vous n'utilisez pas Chrome.
Utilisez staticFile() pour les fichiers dans public/ ou passez 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 une composition connectée.
Son texte est passé en tant que children et accentColor est une propriété modifiable.
La transition en fondu est animée en ligne au 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="Fond"
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 de produits
</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 de produits",
accentColor: "#0b84f3",
}}
/>
</>
);
};
Retarder, couper
Placez le timing directement sur les composants qui le supportent. Voir Propriétés de timing pour les propriétés prises en charge, les exemples et l'ordre des opérations.
Cartes
Voir Remotion Maps si vous souhaitez inclure des cartes dans la vidéo.
Surbrillances de texte et annotations
Voir text-highlights.md pour les surbrillances 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 faire une vidéo avec plusieurs scènes consécutives.
Compositions connectées
Lorsqu'une scène ou un groupe de couches 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 Lueur ambiante (src/BarChart.tsx:134), trouvez le balisage de la séquence sélectionnée à l'emplacement donné. Créez une composition connectée, en suivant connected-compositions.md : extrayez le balisage 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é avec un <Composition> unique dans la racine. Rendez le composant interactif directement avec ses propriétés de timing, ou comme 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 de dimensions, fps, durée et defaultProps équivalents à son utilisation parente. Une extraction de composant sans composition enregistrée ne complète pas une demande de pré-composition.
Transmettez les styles hérités comme fontFamily et le chargement de polices dans le composant extrait ; voir indépendance parentale.
Voix off
Voir voiceover.md pour ajouter une voix off générée par IA aux compositions Remotion en utilisant ElevenLabs TTS.
Incrustation de vidéos
Voir embedding-videos.md pour des connaissances avancées sur l'incrustation de vidéos - coupe, volume, vitesse, boucle, hauteur.
Incrustation d'audio
Voir audio.md pour des fonctionnalités audio avancées comme la coupe, le volume, la vitesse, la hauteur.
Recadrage
Voir cropping.md si vous devez 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 HTML-dans-canvas préférée, les exigences de prévisualisation et les alternatives.
Effets visuels et de pixels
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 propriété effects d'un <Video> lorsque le vignettage doit
affecter cette vidéo.
Ces composants acceptent directement effects :
| Importé depuis | 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 directement effects. Pour appliquer des effets à leur contenu,
encapsulez-les dans <HtmlInCanvas> et mettez la propriété effects sur le wrapper.
Pour les autres éléments, préférez le HTML et CSS réguliers lorsque c'est approprié. Envisagez d'encapsuler
un groupe dans <HtmlInCanvas> lorsque le post-traitement de l'ensemble du
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(),trail(). - Distorsion et transformation :
billowDistortion(),mirror(),perspective(),pinchDistortion(),pixelate(),polaroid(),rippleDistortion(),scatter(),tile(),twirlDistortion(),waveDistortion(),zoom(),dropShadow(),glow(),vignette(). - Composition :
chromaKey(),displacementMap(),lumaChromaKey(),overlay(),shiftChannels(). - Génération :
regularPolygon(),roundedRectangle(),stars(),sunburst(). - Gradients :
linearGradient(),linearGradientTint(),radialGradient().