Remotion — Créer des vidéos avec React et TypeScript (Tutoriel 2026)

Des vidéos, mais en composants React. Remotion vous permet de créer des motion graphics, des intros animées, des visualisations de données et des productions vidéo complètes — entièrement en TypeScript. Sans After Effects. Sans éditeur de timeline. Juste du code.
Ce que vous apprendrez
À la fin de ce tutoriel, vous serez capable de :
- Comprendre l'architecture et les concepts fondamentaux de Remotion
- Configurer un projet Remotion from scratch avec TypeScript
- Construire des compositions animées avec des composants React
- Travailler avec les springs, l'interpolation et l'audio
- Créer une vidéo basée sur les données avec du contenu dynamique
- Exporter votre vidéo en fichier MP4
- Déployer un pipeline de rendu pour la génération automatique de vidéos
Prérequis
Avant de commencer, assurez-vous d'avoir :
- Node.js 20+ installé (
node --version) - Des connaissances en React et TypeScript (hooks, composants, JSX)
- Un éditeur de code — VS Code recommandé
- ffmpeg installé pour le rendu (
brew install ffmpegsur macOS) - Une compréhension basique des animations CSS et des transformations
Pourquoi Remotion ?
Les outils de montage vidéo traditionnels sont parfaits pour les projets ponctuels. Mais que faire si vous devez :
- Générer des centaines de vidéos personnalisées pour des campagnes marketing
- Créer des visualisations de données qui se mettent à jour automatiquement
- Concevoir des intros et outros cohérentes pour tout votre contenu
- Produire des clips pour les réseaux sociaux à grande échelle avec des textes dynamiques
Remotion résout ce problème en traitant les images vidéo comme des composants React. Chaque image est une fonction du temps — vous écrivez du JSX, et Remotion le convertit image par image en un vrai fichier vidéo.
Concepts clés
| Concept | Description |
|---|---|
| Composition | Définition vidéo avec largeur, hauteur, FPS et durée |
| Sequence | Wrapper temporel qui retarde l'apparition d'un composant |
| useCurrentFrame() | Hook qui retourne le numéro de frame actuel |
| useVideoConfig() | Hook qui retourne les métadonnées vidéo |
| interpolate() | Mappe une plage de frames vers une plage de valeurs |
| spring() | Courbe d'animation physique pour un mouvement naturel |
Étape 1 : Configuration du projet
Créez un nouveau projet Remotion avec le starter officiel :
npx create-video@latest my-video --template blank
cd my-videoCela génère un projet TypeScript entièrement configuré. Voici la structure :
my-video/
├── src/
│ ├── Root.tsx # Point d'entrée — enregistre les compositions
│ ├── Composition.tsx # Votre premier composant vidéo
│ └── index.ts # Entrée Remotion
├── remotion.config.ts # Configuration Remotion
├── package.json
└── tsconfig.json
Installez les dépendances et lancez le serveur de prévisualisation :
npm install
npm startCela ouvre le Remotion Studio à http://localhost:3000 — un environnement de prévisualisation dans le navigateur où vous pouvez naviguer dans votre timeline en temps réel.
Étape 2 : Comprendre la Composition
Ouvrez src/Root.tsx. C'est ici que vous enregistrez vos compositions vidéo :
import { Composition } from "remotion";
import { MyComposition } from "./Composition";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="MyVideo"
component={MyComposition}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
/>
</>
);
};Propriétés clés :
- id — Identifiant unique utilisé lors du rendu
- durationInFrames — Nombre total de frames (150 frames à 30fps = 5 secondes)
- fps — Images par seconde (30 standard, 60 pour un mouvement fluide)
- width/height — Résolution vidéo en pixels
Étape 3 : Construire votre première animation
Remplacez src/Composition.tsx par une carte de titre animée :
import { useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion";
import React from "react";
export const MyComposition: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// Animation spring pour le titre
const titleScale = spring({
frame,
fps,
config: {
damping: 12,
stiffness: 200,
mass: 0.5,
},
});
// Apparition du sous-titre après 20 frames
const subtitleOpacity = interpolate(frame, [20, 40], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
// Glissement du sous-titre vers le haut
const subtitleY = interpolate(frame, [20, 40], [30, 0], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<div
style={{
flex: 1,
background: "linear-gradient(135deg, #0f0c29, #302b63, #24243e)",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
fontFamily: "Inter, sans-serif",
}}
>
<h1
style={{
fontSize: 80,
color: "white",
fontWeight: 900,
transform: `scale(${titleScale})`,
textAlign: "center",
}}
>
Bonjour, Remotion
</h1>
<p
style={{
fontSize: 32,
color: "#a8a8ff",
opacity: subtitleOpacity,
transform: `translateY(${subtitleY}px)`,
marginTop: 20,
}}
>
Des vidéos propulsées par React
</p>
</div>
);
};Sauvegardez le fichier et vérifiez dans Remotion Studio — vous verrez une animation fluide où le titre apparaît avec un effet spring, suivi d'un sous-titre qui s'estompe et glisse vers le haut.
Comment ça marche
useCurrentFrame()retourne la frame actuelle (0, 1, 2, ... 149)spring()crée une courbe physique qui commence à 0 et se stabilise à 1interpolate()mappe des plages de frames vers des valeurs — les frames 20-40 mappent l'opacité de 0 à 1extrapolateLeft/Right: "clamp"empêche les valeurs de descendre en dessous de 0 ou au-dessus de 1
Étape 4 : Utiliser les Sequences pour le timing
Les Sequences vous permettent de composer plusieurs sections animées avec un timing précis :
import {
useCurrentFrame,
useVideoConfig,
interpolate,
spring,
Sequence,
AbsoluteFill,
} from "remotion";
import React from "react";
const Title: React.FC<{ text: string }> = ({ text }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({ frame, fps, config: { damping: 12 } });
const opacity = interpolate(frame, [0, 15], [0, 1], {
extrapolateRight: "clamp",
});
return (
<AbsoluteFill
style={{
justifyContent: "center",
alignItems: "center",
}}
>
<h1
style={{
fontSize: 72,
color: "white",
transform: `scale(${scale})`,
opacity,
fontWeight: 800,
}}
>
{text}
</h1>
</AbsoluteFill>
);
};
const FadeOut: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 10], [1, 0], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return <AbsoluteFill style={{ opacity }}>{children}</AbsoluteFill>;
};
export const MyComposition: React.FC = () => {
return (
<AbsoluteFill
style={{
background: "linear-gradient(135deg, #0f0c29, #302b63, #24243e)",
}}
>
{/* Scène 1 : Intro (frames 0-59) */}
<Sequence from={0} durationInFrames={60}>
<Title text="Bienvenue" />
</Sequence>
{/* Scène 2 : Message principal (frames 45-119) */}
<Sequence from={45} durationInFrames={75}>
<Title text="Créez des vidéos avec du code" />
</Sequence>
{/* Scène 3 : Outro avec fondu (frames 110-150) */}
<Sequence from={110} durationInFrames={40}>
<FadeOut>
<Title text="C'est parti !" />
</FadeOut>
</Sequence>
</AbsoluteFill>
);
};Notez comment Sequence réinitialise useCurrentFrame() à 0 dans ses enfants. Cela signifie que chaque composant démarre son animation depuis la frame 0, quel que soit le moment où il apparaît dans la timeline.
Étape 5 : Ajouter de l'audio
Remotion prend en charge l'audio avec une synchronisation précise au niveau de la frame :
import { Audio, Sequence, staticFile } from "remotion";
// Placez votre fichier audio dans le dossier /public
// ex : public/music.mp3
export const MyComposition: React.FC = () => {
return (
<AbsoluteFill style={{ background: "#0f0c29" }}>
{/* Musique de fond dès la frame 0 */}
<Audio src={staticFile("music.mp3")} volume={0.3} />
{/* Effet sonore à la frame 30 */}
<Sequence from={30}>
<Audio src={staticFile("whoosh.mp3")} volume={0.8} />
</Sequence>
{/* Votre contenu visuel */}
<Sequence from={0}>
<Title text="Avec du son !" />
</Sequence>
</AbsoluteFill>
);
};Vous pouvez aussi contrôler dynamiquement le volume :
<Audio
src={staticFile("music.mp3")}
volume={(f) =>
interpolate(f, [0, 30, 120, 150], [0, 0.5, 0.5, 0], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
})
}
/>Étape 6 : Vidéos basées sur les données
C'est ici que Remotion brille vraiment. Construisons une vidéo qui affiche des données dynamiques — imaginez générer automatiquement des vidéos de statistiques hebdomadaires :
import React from "react";
import {
useCurrentFrame,
useVideoConfig,
interpolate,
spring,
Sequence,
AbsoluteFill,
} from "remotion";
interface StatsProps {
title: string;
stats: Array<{ label: string; value: number; color: string }>;
}
const AnimatedBar: React.FC<{
label: string;
value: number;
maxValue: number;
color: string;
delay: number;
}> = ({ label, value, maxValue, color, delay }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const progress = spring({
frame: frame - delay,
fps,
config: { damping: 15, stiffness: 100 },
});
const width = interpolate(progress, [0, 1], [0, (value / maxValue) * 100]);
const labelOpacity = interpolate(frame, [delay, delay + 10], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<div style={{ marginBottom: 24, opacity: labelOpacity }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
marginBottom: 8,
fontSize: 24,
color: "white",
fontFamily: "Inter, sans-serif",
}}
>
<span>{label}</span>
<span style={{ fontWeight: 700 }}>
{Math.round(value * progress)}
</span>
</div>
<div
style={{
height: 32,
background: "rgba(255,255,255,0.1)",
borderRadius: 16,
overflow: "hidden",
}}
>
<div
style={{
height: "100%",
width: `${width}%`,
background: `linear-gradient(90deg, ${color}, ${color}aa)`,
borderRadius: 16,
}}
/>
</div>
</div>
);
};
export const StatsVideo: React.FC<StatsProps> = ({ title, stats }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const titleScale = spring({ frame, fps, config: { damping: 12 } });
const maxValue = Math.max(...stats.map((s) => s.value));
return (
<AbsoluteFill
style={{
background: "linear-gradient(180deg, #1a1a2e, #16213e)",
padding: 80,
justifyContent: "center",
}}
>
<h1
style={{
fontSize: 56,
color: "white",
fontWeight: 900,
marginBottom: 60,
transform: `scale(${titleScale})`,
fontFamily: "Inter, sans-serif",
}}
>
{title}
</h1>
{stats.map((stat, i) => (
<AnimatedBar
key={stat.label}
label={stat.label}
value={stat.value}
maxValue={maxValue}
color={stat.color}
delay={i * 15 + 10}
/>
))}
</AbsoluteFill>
);
};Enregistrez la composition avec des props par défaut dans Root.tsx :
<Composition
id="WeeklyStats"
component={StatsVideo}
durationInFrames={180}
fps={30}
width={1080}
height={1080}
defaultProps={{
title: "Performance de la semaine",
stats: [
{ label: "Nouveaux utilisateurs", value: 1247, color: "#6366f1" },
{ label: "Pages vues", value: 8432, color: "#22d3ee" },
{ label: "Conversions", value: 342, color: "#f43f5e" },
{ label: "Revenus ($)", value: 5890, color: "#10b981" },
],
}}
/>Vous avez maintenant un composant vidéo de statistiques réutilisable. Changez les props et vous obtenez une vidéo complètement différente.
Étape 7 : Charger des polices personnalisées
Utilisez @remotion/google-fonts ou chargez des polices manuellement :
npm install @remotion/google-fontsimport { loadFont } from "@remotion/google-fonts/Inter";
const { fontFamily } = loadFont();
<h1 style={{ fontFamily }}>Stylé avec Inter</h1>Pour les polices locales, placez-les dans le dossier public/ et utilisez staticFile() :
import { staticFile } from "remotion";
const fontFace = new FontFace("MyFont", `url(${staticFile("fonts/MyFont.woff2")})`);
React.useEffect(() => {
document.fonts.add(fontFace);
fontFace.load();
}, []);Étape 8 : Rendu de votre vidéo
Rendu CLI
Exportez votre vidéo en MP4 depuis la ligne de commande :
npx remotion render MyVideo out/my-video.mp4Options de personnalisation :
npx remotion render MyVideo out/my-video.mp4 \
--codec h264 \
--quality 80 \
--concurrency 4| Option | Description |
|---|---|
--codec | h264 (MP4), vp8/vp9 (WebM), prores (MOV) |
--quality | 0-100, qualité JPEG des frames |
--concurrency | Nombre de threads de rendu parallèles |
--props | Chaîne JSON pour surcharger les props par défaut |
Rendu avec des props personnalisées
npx remotion render WeeklyStats out/stats-week-14.mp4 \
--props='{"title":"Stats Semaine 14","stats":[{"label":"Utilisateurs","value":2000,"color":"#6366f1"}]}'Étape 9 : Rendu via l'API Node.js
Pour les pipelines automatisés, utilisez l'API programmatique :
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
import path from "path";
async function renderVideo() {
const bundleLocation = await bundle({
entryPoint: path.resolve("./src/index.ts"),
});
const composition = await selectComposition({
serveUrl: bundleLocation,
id: "WeeklyStats",
inputProps: {
title: "Rapport Avril 2026",
stats: [
{ label: "Revenus", value: 12500, color: "#10b981" },
{ label: "Utilisateurs", value: 3400, color: "#6366f1" },
],
},
});
await renderMedia({
composition,
serveUrl: bundleLocation,
codec: "h264",
outputLocation: "out/april-report.mp4",
onProgress: ({ progress }) => {
console.log(`Rendu : ${Math.round(progress * 100)}%`);
},
});
console.log("Vidéo rendue avec succès !");
}
renderVideo();Étape 10 : Techniques avancées
Fonctions d'easing
Remotion fournit des courbes d'easing intégrées :
import { Easing, interpolate } from "remotion";
const value = interpolate(frame, [0, 30], [0, 1], {
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
extrapolateRight: "clamp",
});Animations décalées
Créez des effets d'entrée en décalant les délais :
const items = ["React", "TypeScript", "Remotion"];
return (
<>
{items.map((item, i) => {
const delay = i * 10;
const opacity = interpolate(frame, [delay, delay + 15], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
const x = interpolate(frame, [delay, delay + 15], [-50, 0], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<p
key={item}
style={{
opacity,
transform: `translateX(${x}px)`,
fontSize: 36,
color: "white",
}}
>
{item}
</p>
);
})}
</>
);Utiliser des images et vidéos
Remotion peut composer des images et intégrer d'autres vidéos :
import { Img, Video, staticFile } from "remotion";
// Image statique
<Img src={staticFile("logo.png")} style={{ width: 200 }} />
// Intégrer une vidéo
<Video src={staticFile("background.mp4")} />Dépannage
Problèmes courants
"ffmpeg not found"
Installez ffmpeg : brew install ffmpeg (macOS) ou apt install ffmpeg (Ubuntu).
Rendu lent
Augmentez la concurrence avec --concurrency 8.
Polices qui ne chargent pas
Utilisez delayRender() pour mettre en pause le rendu le temps que les polices se chargent :
import { delayRender, continueRender } from "remotion";
const [handle] = React.useState(() => delayRender());
React.useEffect(() => {
const font = new FontFace("MyFont", `url(${staticFile("font.woff2")})`);
font.load().then(() => {
document.fonts.add(font);
continueRender(handle);
});
}, [handle]);Idées de projets
- Templates d'intros YouTube — Animations brandées pour votre chaîne
- Générateur de stories réseaux sociaux — Remplir dynamiquement des infos produit dans des templates
- Vidéos de walkthrough de code — Animer l'apparition du code ligne par ligne
- Compteurs à rebours — Compte à rebours animé vers une date de lancement
- Audiogrammes de podcasts — Visualisations de formes d'onde synchronisées avec l'audio
Prochaines étapes
- Explorez la documentation Remotion pour les fonctionnalités avancées comme
OffthreadVideo, le rendu Lambda et l'intégration Player - Découvrez les templates Remotion prêts pour la production
- Apprenez Remotion Lambda pour le rendu de vidéos à grande échelle sur AWS
- Combinez avec Motion (Framer Motion) pour des animations UI complexes dans vos vidéos
Conclusion
Remotion transforme la création vidéo d'un processus manuel dépendant d'outils créatifs en un workflow programmable, reproductible et scalable. En traitant chaque frame comme un composant React, vous bénéficiez de toute la puissance de TypeScript, des packages npm et de la composition de composants — appliquée à la vidéo.
Que vous construisiez du contenu marketing automatisé, des visualisations de données ou des templates brandés, Remotion vous offre l'expérience développeur que vous connaissez et appréciez déjà. Commencez par des animations simples, composez-les en séquences, et bientôt vous exporterez des vidéos de qualité production entièrement depuis le code.
Discutez de votre projet avec nous
Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.
Trouvons les meilleures solutions pour vos besoins.
Articles connexes

Capacitor + React — Créer des applications mobiles multiplateformes depuis votre app web (2026)
Transformez votre application web React en app native iOS et Android avec Capacitor. Ce tutoriel pratique couvre la configuration, les plugins natifs, la caméra, le stockage local, le déploiement sur les stores et les bonnes pratiques de production.

Construire des applications collaboratives Local-First avec Yjs et React
Apprenez à construire des applications collaboratives en temps réel fonctionnant hors ligne avec les CRDTs Yjs et React. Ce tutoriel couvre la synchronisation sans conflits, l'architecture offline-first et la création d'un éditeur de documents partagé.

Authentifier votre application Next.js 15 avec Auth.js v5 : Email, OAuth et contrôle des rôles
Apprenez à ajouter une authentification prête pour la production à votre application Next.js 15 avec Auth.js v5. Ce guide complet couvre Google OAuth, les identifiants email/mot de passe, les routes protégées, le middleware et le contrôle d'accès basé sur les rôles.