Communitygithub.com

Remotion Compose

Transforme un brief vidéo en langage naturel en une composition Remotion complète et prête à être prévisualisée : extrait la durée, les scènes, les couleurs de marque, le rapport hauteur/largeur et le texte réel ; planifie le budget d'images ; et écrit du React/TypeScript basé sur les données utilisant useCurrentFrame, interpolate, spring, AbsoluteFill et Sequence, enregistré dans Root.tsx. À utiliser lorsque quelqu'un demande de créer une vidéo.

Qu'est-ce que Remotion Compose ?

Remotion Compose est un outil d'IA conçu pour les agents comme Claude Code ou Cursor. Il prend un brief en langage naturel et génère automatiquement une composition Remotion complète en React/TypeScript, prête à être prévisualisée dans Studio ou rendue avec remotion-render. L'outil extrait automatiquement la durée, les scènes, les couleurs de marque, le rapport hauteur/largeur et le texte réel, puis construit un plan d'images détaillé avant d'écrire le code. Il utilise les API clés de Remotion : useCurrentFrame, interpolate, spring, AbsoluteFill et Sequence, et enregistre le tout dans src/compositions/ et src/Root.tsx. Il est conçu pour les démos produits, vidéos marketing ou callouts de fonctionnalités, et peut gérer les formats 16:9, 9:16 ou 1:1. L'outil garantit que chaque valeur animée est une fonction pure de useCurrentFrame, que le budget d'images correspond exactement à la durée totale, et que tout le texte et les couleurs sont passés via des props typées avec des valeurs par défaut.

Compatible avec~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SkillMedev/tutorial-video-studio/tree/main/skills/remotion-compose

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait Remotion Compose ?

Vous transformez un brief en langage naturel en une composition Remotion complète et prête à être prévisualisée – du vrai React/TypeScript avec animation pilotée par les images. Le résultat est un fichier .tsx dans src/compositions/, enregistré dans src/Root.tsx, que l'utilisateur peut immédiatement parcourir dans Studio ou confier à remotion-render.

Déclenchez-vous sur toute demande de création, génération, animation ou "écris le code vidéo pour" une démo produit, une présentation, un callout de fonctionnalité ou une animation marketing – y compris "construis une vidéo de 20 secondes montrant X".

Étape 1 – Extraire le brief

Ne commencez pas à coder avant d'avoir ces éléments. Posez-les en un seul lot compact ; comblez les lacunes évidentes avec des valeurs par défaut sensées plutôt que de bloquer :

  1. Durée en secondes, et fps (par défaut 30 – le standard pour les vidéos produit et marketing, et la moitié du coût de rendu du 60. Utilisez 60fps uniquement pour animer des mouvements fins de curseur ou des UI défilantes où le 30 bégaye visiblement).
  2. Scènes – ce qui se passe, dans l'ordre. Poussez pour une liste de beats : "logo, puis trois fonctionnalités, puis un CTA" plutôt que "une démo de mon app".
  3. Marque – couleurs hexadécimales primaire/accent/arrière-plan, et la police (un nom de famille @remotion/google-fonts).
  4. Rapport hauteur/largeur / plateforme – 16:9 paysage (1920×1080), 9:16 portrait (1080×1920) pour les réseaux sociaux, ou 1:1 carré (1080×1080).
  5. Texte – les véritables titres/noms de fonctionnalités/texte CTA. N'inventez jamais de revendications produit ; demandez les vrais mots.

Convertissez les secondes en images partout : durationInFrames = secondes * fps. Longueurs totales typiques : 15-60s pour une démo sociale/produit, 6-15s pour une coupure pub.

Étape 2 – Construire un plan de scènes

Une <Composition> par vidéo, un composant par scène, assemblés sur la timeline avec <Sequence>. Établissez le budget d'images avant d'écrire le code :

Total : 20s @ 30fps = 600 images
  Intro (logo)        images   0-90    (Sequence from=0   durationInFrames=90)
  Fonctionnalité 1    images  90-240   (Sequence from=90  durationInFrames=150)
  Fonctionnalité 2    images 240-390   (Sequence from=240 durationInFrames=150)
  Fonctionnalité 3    images 390-540   (Sequence from=390 durationInFrames=150)
  CTA outro           images 540-600   (Sequence from=540 durationInFrames=60)

Seuils de rythme lors de l'établissement du budget :

  • Donnez à tout beat qui porte du texte au moins 2 secondes (60 images à 30fps) – animation d'entrée plus maintien. Un titre a besoin d'environ 150-200ms de maintien par mot pour être lisible ; un titre de 6 mots veut ~1s de maintien après son arrivée.
  • Animations d'entrée : 10-20 images. Fondu enchaîné et sorties : 12-15 images. Plus long semble lent, plus court semble un glitch.
  • Aucune scène plus courte qu'environ 45 images sauf s'il s'agit d'un flash délibéré.

<Sequence from={F}> décale l'horloge locale des enfants de sorte qu'à l'intérieur de ce composant useCurrentFrame() commence à 0. Animez chaque scène comme si elle commençait à l'image 0.

Étape 3 – Référence API principale

  • useCurrentFrame() – l'image courante (l'horloge). Tout s'anime en fonction de cela.
  • useVideoConfig() – { fps, width, height, durationInFrames }.
  • interpolate(frame, [imagesEntree], [valeursSortie], opts) – mappage linéaire. Passez toujours { extrapolateLeft: "clamp", extrapolateRight: "clamp" } pour les entrées/sorties afin que les valeurs ne dépassent pas leur plage.
  • spring({ frame, fps, config }) – 0→1 basé sur la physique (légèrement overshoot). Utilisez pour tout ce qui doit sembler vivant (pops, glissements, zooms).
  • AbsoluteFill – un div plein écran positionné en absolu ; la couche de base de chaque scène.
  • Sequence – décale temporellement et limite temporellement les enfants (le planificateur de scènes).
  • Series / Series.Sequence – scènes consécutives sans calcul manuel des décalages from.
  • Img, staticFile – voir Étape 6.

Étape 4 – spring() vs interpolate()

Utilisez spring() quand…Utilisez interpolate() quand…
Le mouvement doit sembler physique – pops, rebonds, zooms, glissementsVous avez besoin d'un contrôle linéaire précis entre des images exactes
Vous voulez un atterrissage naturel / overshootFondu (opacité 0→1), changements de couleur, barres de progression, tout ce qui est chronométré à l'image
Entrées de cartes, logos, badgesFondu enchaîné et sorties où l'overshoot semblerait faux

Schéma – pilotez une transformation avec un spring, une opacité avec interpolate :

const { fps } = useVideoConfig();
const frame = useCurrentFrame();
const pop = spring({ frame, fps, config: { damping: 200 } });   // 0 → 1, vivant
const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
const scale = interpolate(pop, [0, 1], [0.8, 1]);

damping: 200 est la configuration de travail – un atterrissage rapide avec un overshoot à peine perceptible. Un damping plus bas (~10-20) rebondit visiblement ; utilisez-le uniquement lorsque le rebond est l'objectif.

Étape 5 – Structure standard de démo produit

Encodez cette forme sauf indication contraire du brief : introduction logo/marque → N callouts de fonctionnalités → outro CTA. Rendez-le piloté par les données (Étape 6) pour que les variantes soient gratuites.

// src/compositions/ProductDemo.tsx
import {
  AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig,
  interpolate, spring,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";

const { fontFamily } = loadFont();

export type Feature = { title: string; body: string };
export type ProductDemoProps = {
  brand: string;
  colors: { bg: string; fg: string; accent: string };
  logoText: string;
  features: Feature[];
  cta: string;
};

const Intro: React.FC<{ text: string; colors: ProductDemoProps["colors"] }> = ({ text, colors }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const s = spring({ frame, fps, config: { damping: 200 } });
  const scale = interpolate(s, [0, 1], [0.7, 1]);
  const opacity = interpolate(frame, [0, 12], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.bg, justifyContent: "center", alignItems: "center" }}>
      <h1 style={{ fontFamily, fontSize: 120, color: colors.fg, transform: `scale(${scale})`, opacity }}>
        {text}
      </h1>
    </AbsoluteFill>
  );
};

const FeatureCallout: React.FC<{ feature: Feature; colors: ProductDemoProps["colors"] }> = ({ feature, colors }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const slide = spring({ frame, fps, config: { damping: 200 } });
  const x = interpolate(slide, [0, 1], [-60, 0]);
  const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.bg, justifyContent: "center", paddingLeft: 160 }}>
      <div style={{ transform: `translateX(${x}px)`, opacity }}>
        <div style={{ fontFamily, fontSize: 32, color: colors.accent, fontWeight: 700, letterSpacing: 2 }}>
          {feature.title.toUpperCase()}
        </div>
        <div style={{ fontFamily, fontSize: 64, color: colors.fg, maxWidth: 1100, marginTop: 16 }}>
          {feature.body}
        </div>
      </div>
    </AbsoluteFill>
  );
};

const Outro: React.FC<{ cta: string; colors: ProductDemoProps["colors"] }> = ({ cta, colors }) => {
  const frame = useCurrentFrame();
  const opacity = interpolate(frame, [0, 18], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.accent, justifyContent: "center", alignItems: "center" }}>
      <h2 style={{ fontFamily, fontSize: 84, color: colors.bg, opacity }}>{cta}</h2>
    </AbsoluteFill>
  );
};

export const ProductDemo: React.FC<ProductDemoProps> = ({ colors, logoText, features, cta }) => {
  const intro = 90;
  const per = 150;
  const outro = 60;
  return (
    <AbsoluteFill>
      <Sequence durationInFrames={intro}>
        <Intro text={logoText} colors={colors} />
      </Sequence>
      {features.map((f, i) => (
        <Sequence key={i} from={intro + i * per} durationInFrames={per}>
          <FeatureCallout feature={f} colors={colors} />
        </Sequence>
      ))}
      <Sequence from={intro + features.length * per} durationInFrames={outro}>
        <Outro cta={cta} colors={colors} />
      </Sequence>
    </AbsoluteFill>
  );
};

Enregistrez-le dans src/Root.tsx, en calculant durationInFrames à partir des mêmes nombres et en fournissant defaultProps :

<Composition
  id="ProductDemo"
  component={ProductDemo}
  durationInFrames={90 + 3 * 150 + 60}
  fps={30}
  width={1920}
  height={1080}
  defaultProps={{
    brand: "Acme",
    colors: { bg: "#0B0B0F", fg: "#FFFFFF", accent: "#6C5CE7" },
    logoText: "Acme",
    features: [
      { title: "Rapide", body: "Livrez en secondes, pas en sprints." },
      { title: "Simple", body: "Un prompt, une vidéo." },
      { title: "Vôtre", body: "Votre marque, votre texte." },
    ],
    cta: "Commencez gratuitement →",
  }}
/>

Pour le portrait/réseaux sociaux, définissez width={1080} height={1920} ; pour le carré, 1080×1080. Gardez les composants identiques – seul le canevas change.

Étape 6 – Props pilotées par les données et ressources statiques

La composition ci-dessus est entièrement pilotée par les données : chaque mot et chaque couleur est une prop. C'est le but – les variantes (nouveau texte, nouvelle palette, texte localisé) ne nécessitent aucune nouvelle invite ; passez simplement des props différentes (remotion-render le fait à partir d'un fichier JSON pour les lots).

Les ressources statiques (logos, captures d'écran, audio) se trouvent dans public/assets/ et sont référencées avec staticFile() – jamais une importation ou un chemin brut :

import { Img, staticFile } from "remotion";
<Img src={staticFile("assets/logo.png")} />

Étape 7 – Sortie

Enregistrez le fichier final dans src/compositions/<NomVideo>.tsx, enregistrez-le dans src/Root.tsx, et dites à l'utilisateur de prévisualiser avec npx remotion studio (http://localhost:3000). Puis passez le relais : "Parcourez-le dans Studio. Dites-moi ce qui doit changer – trop rapide, mauvaise couleur, texte différent – et je modifie et relance le rendu (remotion-render)."

À NE PAS FAIRE

  • N'animez PAS avec des transitions/animations CSS ou setTimeout/setInterval. Remotion rend les images indépendamment et en parallèle ; tout ce qui n'est pas dérivé de useCurrentFrame() est invisible ou incohérent dans le rendu final même si cela peut sembler correct dans l'aperçu du navigateur.
  • N'utilisez PAS Math.random() pour les effets de particules dispersés – chaque worker de rendu obtient des valeurs différentes et les images cessent de correspondre. Utilisez random(seed) de Remotion pour un pseudo-aléatoire déterministe.
  • Ne récupérez PAS de données et n'attendez PAS de travail asynchrone sans delayRender() / continueRender() – le renderer capture l'image avant l'arrivée des données.
  • Ne codez PAS en dur fps, width ou height dans les composants de scène – lisez-les depuis useVideoConfig() pour que le passage de 30↔60fps ou paysage↔portrait ne casse pas chaque timing et disposition.
  • N'omettez PAS extrapolateLeft/Right: "clamp" sur les interpolations d'entrée/sortie – l'opacité monte au-dessus de 1 et les éléments dérivent hors du canevas après la fin de leur plage.
  • N'inventez PAS de titres, de revendications de fonctionnalités ou de CTA – utilisez le vrai texte de l'utilisateur, et demandez-le s'il manque.

Barre de qualité

  • Chaque valeur animée est une fonction pure de useCurrentFrame() (plus les props) – parcourir en arrière dans Studio est identique à avancer.
  • Le budget d'images dans le plan correspond exactement à durationInFrames dans Root.tsx, et aucun beat textuel ne tient moins que son minimum lisible.
  • Tout le texte et les couleurs arrivent via des props typées avec defaultProps fournies – aucun littéral enterré dans les composants de scène.
  • Les ressources sont chargées via staticFile() ; le fichier s'enregistre proprement et s'affiche dans Studio sans erreur console.

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Captions From Transcript

Produce an accurate, properly timed caption track (SRT or WebVTT) from a video

Kinetic Typography

Put text in motion the right way - title cards, animated captions, lower-thirds, callouts, and word-by-word reveals - with a reading-time-per-word budget so copy holds long enough to read, plus enter/exit timing, weight and size transitions, and type hierarchy in motion. Use when someone asks to

Motion Design Principles

The craft layer for motion: pick the right easing (ease-in / ease-out / ease-in-out / spring), get timing and spacing right, build the anticipation→action→follow-through arc, and apply Disney

Narration Script

Write the spoken voiceover for a tutorial or demo - the actual words, phrased for the ear and synced one-instruction-per-action to what is on screen, with a pacing budget and a confident, jargon-checked tone. Use when someone says

Product Demo Director

Direct the craft of putting a real software UI on screen - cursor choreography, zoom/pan/callout language, screen-recording vs recreated-UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking

Remotion Render

Renders a Remotion composition to MP4 and runs the edit-and-re-render loop - CLI render commands, 1080p/4K/9:16 presets, concurrency tuning, codec selection, batch variants from a JSON data file, and Lambda for cloud rendering. Use when someone says

Remotion Setup

Scaffolds a new Remotion video project wired for Claude Code Agent Skills - Node check, create-video scaffold, skills install, folder conventions, Google Fonts, and a smoke-test render. Use whenever someone wants to start making videos with Remotion and Claude, even just

Screencast Capture

Capture clean raw screen and camera footage for a tutorial or product demo - choosing the recorder (macOS Screenshot toolbar, QuickTime, OBS, Windows Game Bar), setting resolution / frame-rate / cursor / microphone, prepping a distraction-free stage, and recording in retakeable segments. Use when someone says

SkillMedev/tutorial-video-studio

Plan a product demo, feature announcement, or launch video as a beat sheet and shot list BEFORE animating - hook in the first 3s, problem, reveal, proof, CTA - with target duration and pacing per scene type, output as a JSON scene plan that remotion-compose consumes directly. Use when someone says

Social Video Formatter

Reframe and export a finished video for social platforms - 9:16 ↔ 16:9 cropping, burned-in captions, a platform-native first frame, loop design, and per-platform specs (aspect, length, safe areas) for TikTok, Reels, Shorts, X, and LinkedIn. Use when someone says

Sound and Music Sync

Score a video like an editor: beat-match cuts to the music, land SFX on transitions, pace the voiceover so it breathes, source royalty-free tracks safely, and duck the music so the VO sits clearly on top. Use when adding music, sound effects, or voiceover to a video, when asked to

Skills associés