ali-abassi/remotion-templates

Modèles vidéo Remotion organisés pour Claude Code et les agents IA de codage – sous-titres, visualiseurs audio, effets, transitions

Qu'est-ce que remotion-templates ?

Cette compétence fournit aux agents de codage IA (comme Claude Code, Cursor, Codex) un ensemble complet de contextes pour créer des vidéos prêtes à la production avec Remotion. Elle inclut des principes de conception vidéo, des modèles organisés (sous-titres de type TikTok, visualisation audio en forme d'onde ou circulaire, vidéos 3D avec Three.js, introductions Instagram Reels et appels à l'action YouTube), ainsi que les meilleures pratiques d'animation. L'utilisateur peut rapidement démarrer avec des commandes d'installation, une structure de projet prédéfinie, et des extraits de code prêts à l'emploi pour gérer le rythme vidéo, la hiérarchie visuelle, les animations de texte synchronisées au son, et les transitions entre scènes. Distribuée via un dépôt GitHub, cette compétence est conçue pour fonctionner avec n'importe quel IDE ou terminal intégrant un assistant IA, et simplifie la création de contenu vidéo à grande échelle.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add ali-abassi/remotion-templates

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

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

Documentation

Objectif

Cette compétence fournit à Claude Code et aux agents IA de codage un contexte complet pour créer des vidéos prêtes à la production avec Remotion. Elle inclut des principes de conception, des modèles organisés et les meilleures pratiques.

Quand l'utiliser

Utilisez cette compétence lorsque vous :

  • Créez du contenu vidéo par programmation avec React
  • Construisez des audiogrammes de podcasts ou des visualisations audio
  • Ajoutez des sous-titres animés aux vidéos (style TikTok/Reels)
  • Créez des présentations de produits en 3D
  • Développez un SaaS de génération vidéo
  • Réalisez des vidéos de visualisation de données
  • Générez du contenu pour les réseaux sociaux à grande échelle

Principes de conception vidéo

1. Rythme et cadence

  • Coupures rapides : 1-2 secondes pour l'énergie (réseaux sociaux)
  • Rythme moyen : 3-5 secondes pour la compréhension (tutoriels)
  • Rythme lent : 5-10 secondes pour l'emphase (cinématographique)
  • Synchronisation audio : Synchronisez les transitions sur les temps forts ou la parole

2. Hiérarchie visuelle

  • Un seul point focal par image
  • Utilisez le mouvement pour guider l'attention
  • Contrastez les éléments importants
  • Maintenez un espacement cohérent

3. Règles pour le texte sur vidéo

  • Maximum 7 mots par image
  • Contraste élevé (blanc sur fond sombre, ou contouré)
  • Laissez le texte à l'écran suffisamment longtemps pour être lu 2 fois
  • Placez-le dans le tiers inférieur ou au centre
  • Évitez les bords (zone de sécurité : marge de 10%)

4. Temporisation des animations

ÉlémentDuréeInterpolation
Apparition du texte8-15 imageseaseOut
Sortie du texte6-10 imageseaseIn
Transition de scène15-30 imageseaseInOut
Révélation de logo30-60 imagesspring
Coupure rapide0-3 imageslinear

5. Fréquences d'images

  • 30 ips : Vidéo standard, réseaux sociaux
  • 60 ips : Mouvement fluide, contenu de jeu
  • 24 ips : Aspect cinématographique
  • 25 ips : Diffusion européenne

6. Ratios d'aspect

PlateformeRatioRésolution
YouTube16:91920x1080
TikTok/Reels9:161080x1920
Fil Instagram1:11080x1080
Story Instagram9:161080x1920
Twitter16:91280x720
LinkedIn16:91920x1080

Démarrage rapide

Installation

# Nouveau projet avec sélection de modèle
npx create-video@latest

# Configuration manuelle
mkdir my-video && cd my-video
npm init -y
npm install remotion @remotion/cli react react-dom
npm install -D typescript @types/react

Structure du projet

src/
├── index.ts           # registerRoot
├── Root.tsx           # Définitions des compositions
├── compositions/
│   ├── Main.tsx       # Vidéo principale
│   └── Intro.tsx      # Séquence d'introduction
├── components/
│   ├── Text.tsx       # Texte animé
│   └── Logo.tsx       # Révélation du logo
└── assets/
    ├── fonts/
    ├── images/
    └── audio/

Modèle Root.tsx

import { Composition } from 'remotion';
import { Main } from './compositions/Main';

export const RemotionRoot = () => {
  return (
    <>
      <Composition
        id="Main"
        component={Main}
        durationInFrames={300}
        fps={30}
        width={1920}
        height={1080}
        defaultProps={{
          title: 'Ma vidéo'
        }}
      />
    </>
  );
};

Modèles de base

Fondamentaux d'animation

import { useCurrentFrame, useVideoConfig, interpolate, spring } from 'remotion';

const frame = useCurrentFrame();
const { fps, width, height, durationInFrames } = useVideoConfig();

// Interpolation linéaire (clampée)
const opacity = interpolate(frame, [0, 30], [0, 1], {
  extrapolateRight: 'clamp'
});

// Animation ressort (rebondissante)
const scale = spring({
  frame,
  fps,
  config: { damping: 12, stiffness: 200 }
});

// Ressort retardé
const delayedScale = spring({
  frame: frame - 15, // Retard de 15 images
  fps,
  config: { damping: 10 }
});

Séquençage

import { Sequence, AbsoluteFill } from 'remotion';

export const MyVideo = () => (
  <AbsoluteFill>
    <Sequence from={0} durationInFrames={60}>
      <Intro />
    </Sequence>
    <Sequence from={60} durationInFrames={120}>
      <MainContent />
    </Sequence>
    <Sequence from={180}>
      <Outro />
    </Sequence>
  </AbsoluteFill>
);

Animation de texte

const TextReveal = ({ text }: { text: string }) => {
  const frame = useCurrentFrame();
  const words = text.split(' ');

  return (
    <div style={{ display: 'flex', gap: 10, justifyContent: 'center' }}>
      {words.map((word, i) => {
        const delay = i * 5;
        const opacity = interpolate(frame - delay, [0, 10], [0, 1], {
          extrapolateLeft: 'clamp',
          extrapolateRight: 'clamp'
        });
        const y = interpolate(frame - delay, [0, 10], [20, 0], {
          extrapolateLeft: 'clamp',
          extrapolateRight: 'clamp'
        });

        return (
          <span key={i} style={{ opacity, transform: `translateY(${y}px)` }}>
            {word}
          </span>
        );
      })}
    </div>
  );
};

Synchronisation audio

import { Audio, useCurrentFrame, interpolate } from 'remotion';
import { getAudioDurationInSeconds } from '@remotion/media-utils';

// Enveloppe de volume
const frame = useCurrentFrame();
const volume = interpolate(frame, [0, 30, 270, 300], [0, 1, 1, 0]);

<Audio src={staticFile('music.mp3')} volume={volume} />

Catalogue de modèles

Sous-titres et légendes

remotion-subtitles (17 styles)

npm install @ahgsql/remotion-subtitles
import { Subtitle } from '@ahgsql/remotion-subtitles';

// Styles disponibles : bounce, fire, glitch, neon, typewriter,
// 3d, lightning, glowing, explosive, wave, slide, fade,
// zoom, rotate, flip, shake, pulse

<Subtitle
  src={staticFile('captions.srt')}
  style='bounce'
  fontSize={48}
  color='#ffffff'
  strokeColor='#000000'
  strokeWidth={2}
/>

Sous-titres style TikTok

const Caption = ({ text, highlight }: { text: string; highlight: number }) => {
  const words = text.split(' ');

  return (
    <div style={{
      position: 'absolute',
      bottom: '20%',
      width: '100%',
      textAlign: 'center',
      fontSize: 64,
      fontWeight: 900,
      textTransform: 'uppercase'
    }}>
      {words.map((word, i) => (
        <span
          key={i}
          style={{
            color: i === highlight ? '#FFE135' : '#FFFFFF',
            textShadow: '4px 4px 0 #000, -4px -4px 0 #000, 4px -4px 0 #000, -4px 4px 0 #000'
          }}
        >
          {word}{' '}
        </span>
      ))}
    </div>
  );
};

Visualisation audio

Visualiseur en forme d'onde

import { useAudioData, visualizeAudio } from '@remotion/media-utils';

const Waveform = ({ src }: { src: string }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const audioData = useAudioData(src);

  if (!audioData) return null;

  const visualization = visualizeAudio({
    fps,
    frame,
    audioData,
    numberOfSamples: 64
  });

  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
      {visualization.map((amplitude, i) => (
        <div
          key={i}
          style={{
            width: 8,
            height: amplitude * 200,
            backgroundColor: '#667eea',
            borderRadius: 4
          }}
        />
      ))}
    </div>
  );
};

Visualiseur audio circulaire

const CircularVisualizer = ({ audioData, frame, fps }) => {
  const visualization = visualizeAudio({ fps, frame, audioData, numberOfSamples: 32 });
  const radius = 150;

  return (
    <svg width={400} height={400} viewBox='0 0 400 400'>
      {visualization.map((amp, i) => {
        const angle = (i / visualization.length) * Math.PI * 2;
        const x1 = 200 + Math.cos(angle) * radius;
        const y1 = 200 + Math.sin(angle) * radius;
        const x2 = 200 + Math.cos(angle) * (radius + amp * 100);
        const y2 = 200 + Math.sin(angle) * (radius + amp * 100);

        return <line key={i} x1={x1} y1={y1} x2={x2} y2={y2} stroke='#667eea' strokeWidth={4} />;
      })}
    </svg>
  );
};

3D avec Three.js

Configuration

npm install @remotion/three three @react-three/fiber @react-three/drei

Maquette de téléphone

import { ThreeCanvas } from '@remotion/three';
import { useFrame } from '@react-three/fiber';

const PhoneMockup = ({ videoSrc }: { videoSrc: string }) => {
  const frame = useCurrentFrame();
  const rotation = interpolate(frame, [0, 150], [0, Math.PI * 2]);

  return (
    <ThreeCanvas>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} />
      <mesh rotation={[0, rotation, 0]}>
        <boxGeometry args={[2, 4, 0.2]} />
        <meshStandardMaterial color='#1a1a2e' />
      </mesh>
    </ThreeCanvas>
  );
};

Modèles pour réseaux sociaux

Introduction Instagram Reel

const ReelIntro = ({ username, avatar }: Props) => {
  const frame = useCurrentFrame();
  const scale = spring({ frame, fps: 30, config: { damping: 12 } });

  return (
    <AbsoluteFill style={{ background: 'linear-gradient(135deg, #667eea, #764ba2)' }}>
      <div style={{
        transform: `scale(${scale})`,
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        height: '100%'
      }}>
        <img
          src={avatar}
          style={{ width: 120, height: 120, borderRadius: '50%', border: '4px solid white' }}
        />
        <h1 style={{ color: 'white', fontSize: 48, marginTop: 20 }}>@{username}</h1>
      </div>
    </AbsoluteFill>
  );
};

Appel à l'action YouTube S'abonner

const SubscribeCTA = () => {
  const frame = useCurrentFrame();
  const slideIn = interpolate(frame, [0, 20], [100, 0], { extrapolateRight: 'clamp' });
  const bellWiggle = Math.sin(frame * 0.5) * 10;

  return (
    <div style={{
      position: 'absolute',
      bottom: 50,
      right: 50,
      transform: `translateX(${slideIn}%)`,
      display: 'flex',
      alignItems: 'center',
      gap: 20,
      background: 'rgba(0,0,0,0.8)',
      padding: '20px 30px',
      borderRadius: 50
    }}>
      <div style={{
        background: '#FF0000',
        padding: '12px 24px',
        borderRadius: 4,
        color: 'white',
        fontWeight: 'bold'
      }}>
        S'ABONNER
      </div>
      <div style={{ transform: `rotate(${bellWiggle}deg)`, fontSize: 32 }}>
        🔔
      </div>
    </div>
  );
};

Bibliothèque d'effets

Effet de glitch

const GlitchText = ({ text }: { text: string }) => {
  const frame = useCurrentFrame();
  const glitchOffset = Math.random() > 0.9 ? Math.random() * 10 - 5 : 0;

  return (
    <div style={{ position: 'relative' }}>
      <span style={{
        position: 'absolute',
        left: glitchOffset,
        color: 'cyan',
        clipPath: 'inset(0 0 50% 0)'
      }}>
        {text}
      </span>
      <span style={{
        position: 'absolute',
        left: -glitchOffset,
        color: 'magenta',
        clipPath: 'inset(50% 0 0 0)'
      }}>
        {text}
      </span>
      <span style={{ color: 'white' }}>{text}</span>
    </div>
  );
};

Champ de particules

const Particles = ({ count = 50 }: { count?: number }) => {
  const frame = useCurrentFrame();
  const particles = useMemo(() =>
    Array.from({ length: count }, () => ({
      x: Math.random() * 100,
      y: Math.random() * 100,
      size: Math.random() * 4 + 2,
      speed: Math.random() * 0.5 + 0.2
    })),
    []
  );

  return (
    <AbsoluteFill style={{ overflow: 'hidden' }}>
      {particles.map((p, i) => (
        <div
          key={i}
          style={{
            position: 'absolute',
            left: `${p.x}%`,
            top: `${(p.y + frame * p.speed) % 100}%`,
            width: p.size,
            height: p.size,
            borderRadius: '50%',
            background: 'rgba(255,255,255,0.5)'
          }}
        />
      ))}
    </AbsoluteFill>
  );
};

Fond dégradé animé

const AnimatedGradient = () => {
  const frame = useCurrentFrame();
  const hue = interpolate(frame, [0, 300], [200, 360], { extrapolateRight: 'clamp' });

  return (
    <AbsoluteFill style={{
      background: `linear-gradient(135deg, hsl(${hue}, 70%, 50%), hsl(${hue + 60}, 70%, 50%))`
    }} />
  );
};

Skills associés