Analyser une vidéo de motion design en profondeur — QUOI, COMMENT, POURQUOI — et générer un DA-template
Tu analyses des vidéos MP4 dans references/pinterest/ pour en extraire un DA-template réutilisable.
OBJECTIF : le DA-template doit contenir ASSEZ DE DÉTAIL pour recréer exactement la même animation avec un scénario similaire. Chaque paramètre, chaque timing, chaque couleur, chaque position doit être documenté.
$ARGUMENTS[0] — nom du fichier MP4 (ex: GatesFX_01.mp4) ou all pour analyser toutes les vidéos non encore analysées.Si aucun argument → all.
src/lib/BIBLE.md — les principes de motion design (pour structurer ton analyse)src/lib/toolkit.tsx — les techniques existantes (pour mapper ce que tu vois)src/lib/effects.tsx — les effets existants (pour mapper ce que tu vois)src/videos/CashflowErreurV6.tsx (RÉFÉRENCE) — niveau de détail attendu (5 Z-layers, camera, staging)Utilise ffmpeg pour extraire des frames régulières + les moments de transition :
VIDEO="references/pinterest/$FICHIER"
TMPDIR=$(mktemp -d)
# Durée totale en secondes
DURATION=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$VIDEO" | cut -d. -f1)
# Extraire 1 frame toutes les 0.2s (5fps — plus précis pour les transitions rapides)
ffmpeg -i "$VIDEO" -vf "fps=5,scale=540:-1" -q:v 2 "$TMPDIR/frame_%04d.jpg" -y 2>/dev/null
# Aussi extraire les infos vidéo
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,duration -of json "$VIDEO"
Lis les frames extraites avec le tool Read (qui supporte les images). Analyse :
Lis les frames dans l'ordre. Regarde-les TOUTES attentivement pour comprendre le flow complet.
Pour chaque frame, note mentalement :
Pour chaque vidéo, produis un JSON avec cette structure DÉTAILLÉE :
{
"name": "...",
"sourceFile": "GatesFX_01.mp4",
"duration": 4.2,
"resolution": "1080x1920",
"fps": 30,
"overview": "Description en 2-3 phrases détaillées",
"quoi": {
"type": "kinetic-typography | logo-reveal | product-showcase | data-viz | transition-reel | explainer | mixed",
"elements": ["texte", "icônes", "shapes", "photos", "3D", "particles"],
"scenes": [
{
"id": "S1",
"timestamp": "0.0-1.5s",
"durationFrames": 45,
"description": "Description DÉTAILLÉE de ce qui se passe visuellement — pas juste 'texte apparaît' mais 'Le mot GROWTH apparaît en blanc 900 weight au centre, scale depuis 3x avec blur 15px qui se dissipe, pendant qu'un line chart se dessine en dessous de gauche à droite'",
"layout": {
"type": "centered | split | fullscreen | grid | diagonal | floating | radial",
"description": "Description précise du placement — ex: 'Texte centré horizontalement à 40% vertical, graphique en dessous à 60%, icône décorative en haut-droite à (85%, 10%)'",
"background": "Description exacte du fond — couleur unie #hex, gradient (direction, couleurs, stops), texture, image, etc."
},
"elements": [
{
"type": "text | icon | shape | image | chart | decoration | particle",
"content": "Le contenu exact (texte, description de l'icône/shape)",
"position": { "x": "center | left | right | 120px | 15%", "y": "center | top | bottom | 780px | 40%" },
"size": "Taille — fontSize en px estimé, ou dimensions de l'élément",
"style": {
"color": "#hex exact",
"fontFamily": "type de font observé (bold condensed sans-serif, thin serif italic, etc.)",
"fontWeight": "100-900 estimé",
"letterSpacing": "normal | tight (-0.02em) | wide (0.05em) | etc.",
"textTransform": "uppercase | lowercase | none",
"additionalCSS": "Tout style notable : textShadow, border, borderRadius, background, opacity initiale, etc."
},
"animation": {
"enter": {
"technique": "scale-explode | slide-up | slide-down | slide-left | slide-right | fade | mask-reveal-horizontal | mask-reveal-vertical | char-stagger | text-scramble | typewriter | split-reveal | counter-roll | draw-on (SVG path) | clip-expand | rotate-in | none",
"from": "Valeur de départ — ex: { scale: 4, blur: 15, opacity: 0, y: 300, rotation: -8 }",
"to": "Valeur finale — ex: { scale: 1, blur: 0, opacity: 1, y: 0, rotation: 0 }",
"delay": "Délai en frames estimé depuis le début de la scène — ex: 0, 4, 8, 12...",
"durationFrames": "Nombre de frames pour l'animation — ex: 8, 12, 18, 24",
"easing": "spring(stiffness, damping, mass) | ease-out | ease-in | ease-in-out | linear | ease-out-back (overshoot)",
"springConfig": "Si spring perçu : { stiffness: 300, damping: 10, mass: 1.3 } — ESTIME les valeurs",
"details": "Tout détail supplémentaire : motion blur pendant le mouvement, chromatic aberration, color shift pendant l'animation, etc."
},
"during": {
"technique": "static | pulse | float | breathe | rotate-slow | shimmer | glow-pulse | counter-roll | none",
"details": "Paramètres — ex: 'pulse scale ±3% à 0.5Hz', 'float Y ±5px sinusoidal', 'glow pulse opacity 0.3-0.6 at 0.06 freq'"
},
"exit": {
"technique": "fade | slide-out | scale-down | blur-out | wipe | cut | accelerate-out | none",
"to": "Valeur de sortie — ex: { opacity: 0, x: 600, blur: 25, scale: 1.3 }",
"durationFrames": "Nombre de frames",
"easing": "ease-in (accelerate) | ease-out | linear",
"details": "Détails supplémentaires"
}
}
}
],
"camera": {
"enter": "Description de l'entrée caméra — ex: 'zoom-out reveal from scale 1.6 to 1, translateX from -150 to 0, blur 15 to 0, rotation 3deg to 0'",
"during": "Mouvement pendant la scène — ex: 'subtle noise2D wander ±12px X, ±8px Y, ±0.5deg rotation, breathing scale ±0.4%'",
"exit": "Sortie caméra — ex: 'accelerate right+up, translateX +600, translateY -400, scale 1.3, blur 25, rotation +3deg over 8 frames'",
"shake": "Si screen shake : 'triggered at frame X, amplitude 8px decaying over 10 frames, freq 4.2Hz X / 5.5Hz Y'"
},
"postProcess": ["Liste des effets post-process actifs : grain, vignette(0.7), light-leak(accent), scan-line-flash, edge-blur, chromatic-aberration(intensity)"]
}
]
},
"comment": {
"palette": {
"background": "#hex — sample exact",
"backgroundGradient": "Si gradient : 'linear-gradient(135deg, #hex1 0%, #hex2 100%)' ou 'radial-gradient(circle at 50% 40%, #hex1 0%, #hex2 60%)'",
"primary": "#hex — couleur principale du texte",
"secondary": "#hex — couleur secondaire",
"accent": "#hex — couleur d'accent (highlights, CTAs)",
"subtle": "#hex — couleur subtile (texte secondaire, décorations)",
"style": "dark-mode | light-mode | mixed | gradient",
"additionalColors": ["#hex — toute autre couleur notable utilisée"]
},
"typography": {
"primary": {
"family": "Type exact de font — ex: 'geometric bold condensed sans-serif (similar to Bebas Neue / Impact)'",
"weights": [400, 700, 900],
"sizes": {
"hero": "~120px — les gros titres d'impact",
"title": "~64px — titres de section",
"subtitle": "~36px — sous-titres",
"body": "~24px — texte courant",
"caption": "~16px — légendes/tags"
},
"style": "uppercase | normal | italic",
"letterSpacing": "tight (-0.02em) | normal | wide (0.05em)",
"lineHeight": "0.9 | 1.0 | 1.2 | 1.4"
},
"secondary": {
"family": "Type de font secondaire — ex: 'elegant thin serif italic (similar to Playfair Display)'",
"weights": [300, 400],
"style": "italic | normal",
"usage": "Pour quoi : sous-titres, citations, annotations, tags"
},
"hierarchy": "Description de la hiérarchie visuelle : 'Un seul mot accent en couleur accent par scène, le reste en white/subtle. Les mots-clés sont 3x plus gros que le texte support.'"
},
"animations": [
{
"element": "Description précise de l'élément",
"technique": "nom technique",
"timing": {
"delayFrames": 0,
"durationFrames": 12,
"totalMs": 500
},
"easing": "type d'easing avec config estimée",
"springConfig": { "stiffness": 300, "damping": 10, "mass": 1.3 },
"from": "Valeurs de départ (scale, position, opacity, blur, rotation...)",
"to": "Valeurs finales",
"details": "Tous les détails additionnels : motion blur, chromatic ab, color transition, overshoot amount, etc."
}
],
"transitions": [
{
"from": "S1",
"to": "S2",
"type": "cut | crossfade | wipe | zoom-punch | blur-transition | morph | slide",
"durationFrames": 8,
"details": "Description précise — ex: 'Camera accelerates right+up with blur 0→25 over 8 frames (ease-in), next scene enters from left+down with blur 20→0 (spring)'",
"overlap": "Nombre de frames de chevauchement entre les scènes (0 = cut)"
}
],
"effects": {
"grain": { "active": true, "intensity": "léger | moyen | fort", "details": "Type de grain — film 35mm, digital noise, scan lines" },
"vignette": { "active": true, "intensity": 0.7, "details": "Douce | dure, couleur sombre ou colorée" },
"blur": { "active": true, "details": "edge-blur périphérique, motion-blur sur mouvement, depth-blur sur layers" },
"glow": { "active": true, "details": "Radial glow accent derrière les éléments clés, radius ~450px, opacity pulsante 0.2-0.4" },
"parallax": { "active": true, "layers": 5, "details": "Z0: 0.15x camera, blur 4px | Z1: 0.3x, blur 1.5px | Z2: 0.55x, sharp | Z3: ancré | Z4: -0.3x inverse, blur 3px" },
"chromatic": { "active": false, "details": "Si oui : quand (enter/exit/impact), intensité" },
"other": ["Tout autre effet remarqué : scan-line-flash, light-leak, bokeh foreground, etc."]
},
"rhythm": {
"type": "saccadé | fluide | crescendo | constant | respiré",
"bpm": "Estimation du tempo visuel — combien de changements par seconde",
"pattern": "Description du pattern : 'intro lente → accélération → impact → respiration → accélération → outro'. Ou 'régulier toutes les 1.5s'. Ou 'staccato rapide avec micro-pauses'",
"sceneDurations": "Durée type des scènes en secondes — ex: '1.2-1.8s par scène, avec une scène longue de 3s pour le climax'"
},
"camera": {
"type": "statique | wander | zoom-in | zoom-out | pan | shake | breathing | combo",
"wander": {
"amplitude": { "x": "±12px", "y": "±8px", "rotation": "±0.5deg", "scale": "±0.4%" },
"frequency": { "x": 0.015, "y": 0.012, "rotation": 0.01, "scale": 0.06 },
"style": "noise2D organique | sinusoidal | random"
},
"enterStyle": "zoom-out reveal | swing-in lateral | drop-in vertical | scale-in | cut",
"exitStyle": "accelerate-out (direction) | fade+blur | punch-out | wipe",
"shake": {
"triggers": "Sur quels événements : impact de mot accent, apparition de stat, transition",
"amplitude": "8-12px",
"decay": "10 frames exponential",
"frequency": "4.2Hz X / 5.5Hz Y"
}
}
},
"pourquoi": {
"mood": "Description détaillée du sentiment / ambiance — pas juste 'corporate' mais 'corporate-confident avec une touche de danger/urgence, comme un rapport financier qui révèle un problème critique'",
"principesAppliques": [
{
"principe": "anticipation | follow-through | staging | easing | arc-motion | secondary-action | exaggeration",
"example": "Où et comment ce principe est appliqué dans la vidéo — ex: 'Le mot 90% shrink de 0.95 avant de scale-explode à 4x (anticipation)'"
}
],
"forces": ["Points forts DÉTAILLÉS — pas juste 'bonne typo' mais 'La hiérarchie typographique crée un rythme de lecture forcé : l'oeil est guidé du mot accent rouge vers le sous-texte italic, puis vers le tag en bas'"],
"faiblesses": ["Points à éviter si on s'en inspire"],
"inspiration": "Comment réutiliser concrètement ce style — quels patterns copier, quels adapter, pour quels types de contenu"
},
"daTemplate": {
"name": "Nom court et évocateur du style (2-3 mots max)",
"description": "Le style en 2-3 phrases détaillées — assez pour visualiser le rendu final",
"palette": {
"dark": "#hex",
"light": "#hex",
"accent": "#hex",
"text": "#hex",
"textDark": "#hex",
"subtle": "#hex",
"gradient": "Si applicable — ex: 'radial-gradient(circle at 50% 35%, #1a0a10 0%, #0a0a0a 70%)'"
},
"fontStyle": {
"primary": {
"description": "Description complète — ex: 'geometric ultra-bold condensed sans-serif (Bebas Neue / Impact / Anton style)'",
"weights": [700, 900],
"sizes": { "hero": "120px", "title": "64px", "body": "28px" },
"style": "uppercase",
"letterSpacing": "-0.02em",
"lineHeight": 0.9,
"color": "#hex principal"
},
"secondary": {
"description": "ex: 'elegant thin serif italic (Playfair Display / Cormorant style)'",
"weights": [300, 400],
"style": "italic",
"color": "#hex",
"usage": "sous-titres, annotations, texte support"
}
},
"elements": {
"types": ["text", "icon", "shape", "line", "particle", "gradient"],
"decorations": [
{
"type": "grid-lines | dots | circles | arcs | noise-texture | bokeh | light-leak | glow-orb | underline | badge | tag | star-burst | separator",
"details": "Description précise — ex: 'grille de 13x22 lignes blanches, strokeWidth 0.5, opacity 0.04, sur tout le canvas'",
"position": "Où dans le canvas",
"animation": "Comment ça bouge — ex: 'draw-on progressif au début de chaque scène, suit la caméra à 0.3x'"
}
],
"layers": {
"count": 5,
"Z0": { "content": "Ghost text 500px + radial glow", "parallax": 0.15, "blur": "4px", "opacity": "0.05-0.15" },
"Z1": { "content": "Grid, arcs SVG, lignes décoratives", "parallax": 0.3, "blur": "1.5px", "opacity": "0.04-0.2" },
"Z2": { "content": "Icônes, particles, shapes SVG, éléments visuels secondaires", "parallax": 0.55, "blur": "0", "opacity": "0.3-0.8" },
"Z3": { "content": "TOUT le texte principal — ANCRÉ, pas de parallax", "parallax": 0, "blur": "0", "opacity": "1" },
"Z4": { "content": "Bokeh foreground, light particles", "parallax": -0.3, "blur": "3px", "opacity": "0.1-0.3" }
}
},
"camera": {
"movement": "combo",
"wander": {
"amplitude": { "x": "±12px", "y": "±8px", "rotation": "±0.5deg", "scale": "±0.4%" },
"frequency": { "x": 0.015, "y": 0.012, "rotation": 0.01, "scale": 0.06 },
"style": "noise2D organique"
},
"enters": {
"technique": "zoom-out reveal | swing-in lateral | drop-in vertical",
"springConfig": { "stiffness": 60, "damping": 22, "mass": 1.3 },
"from": "Description — ex: { scale: 1.6, translateX: -150, translateY: 80, rotation: 3, blur: 15 }",
"durationFrames": 18
},
"exits": {
"technique": "accelerate-out directional",
"easing": "ease-in (accelerating)",
"to": "Description — ex: { translateX: 600, translateY: -400, scale: 1.3, rotation: 3, blur: 25 }",
"durationFrames": 8
},
"shake": {
"trigger": "Impact du mot accent",
"amplitude": "8px X, 6px Y",
"decay": "10 frames exponential (factor 0.1/frame)",
"frequency": "4.2Hz X / 5.5Hz Y"
}
},
"elementMotion": [
{
"element": "Description — ex: 'Mot accent (stat, mot-clé émotionnel)'",
"enter": {
"technique": "scale-explode | slide-up | char-stagger | etc.",
"from": { "scale": 4, "blur": 15, "opacity": 0, "rotation": -8 },
"to": { "scale": 1, "blur": 0, "opacity": 1, "rotation": 0 },
"springConfig": { "stiffness": 300, "damping": 10, "mass": 1.3 },
"delayFrames": 6,
"details": "Tout détail : chromatic aberration pendant l'animation, color shift (white→accent), motion blur"
},
"during": {
"technique": "glow-pulse | static | float",
"details": "Paramètres : 'textShadow glow pulsing 0→80px→0 at freq 0.06, color accent at 40% opacity'"
},
"exit": {
"technique": "accelerate-out | fade | cut",
"to": { "x": 600, "blur": 25, "scale": 1.3 },
"durationFrames": 8,
"easing": "ease-in"
}
},
{
"element": "Texte support (sous-titre, explication)",
"enter": {
"technique": "fade-slide",
"from": { "y": -40, "opacity": 0 },
"to": { "y": 0, "opacity": 1 },
"springConfig": { "stiffness": 100, "damping": 24, "mass": 1 },
"delayFrames": 2
},
"during": { "technique": "static" },
"exit": { "technique": "fade", "durationFrames": 6 }
},
{
"element": "Icône / shape décorative",
"enter": {
"technique": "draw-on + scale + rotate",
"from": { "scale": 0.3, "rotation": -15, "strokeDashoffset": "100%" },
"to": { "scale": 1, "rotation": 0, "strokeDashoffset": "0%" },
"springConfig": { "stiffness": 45, "damping": 16, "mass": 1.2 },
"delayFrames": 1
},
"during": { "technique": "static", "details": "Opacity 0.5" },
"exit": { "technique": "with camera exit" }
}
],
"sceneStructure": {
"template": "Structure type d'une scène en frames — ex: 'frames 0-3: camera open blur→sharp | frames 2-4: Z0/Z1 décor | frames 4-8: texte setup | frames 8-16: MOT ACCENT + shake | frames 16-18: secondary actions | frames 20-24: texte complémentaire | frames 28-36: camera exit'",
"averageDurationFrames": 36,
"elementSpacing": "Nombre de frames entre chaque nouvel élément — ex: '2-4 frames (overlapping action)'",
"accentIsolation": "Le mot accent arrive SEUL — rien d'autre ne bouge pendant 4-6 frames",
"impactPattern": "Description du pattern d'impact — ex: 'scale-explode → 2 frames → screen shake → 2 frames → expanding ring → hold'"
},
"signatureAnimations": [
{
"name": "Nom descriptif — ex: 'scale-explode-with-chromatic'",
"description": "Description complète de comment reproduire l'animation",
"toolkitMapping": "Quel composant toolkit utiliser — ex: 'Manual interpolate (pas de composant toolkit existant)' ou 'CharStagger from=bottom'",
"params": "Paramètres clés à reproduire"
}
],
"signatureEffects": [
{
"name": "ex: 'radial-glow-accent'",
"description": "Description pour reproduire — ex: 'Radial gradient derrière le mot accent, 900px diameter, couleur accent à 15-40% opacity pulsante, blur 4px'",
"effectsMapping": "Quel composant effects.tsx utiliser — ex: 'Ghost + custom radial-gradient div'"
}
],
"imageStyle": {
"description": "Comment reproduire le style visuel des images/illustrations utilisées dans la vidéo — TRÈS DÉTAILLÉ",
"type": "photo-stock | flat-illustration | 3D-render | collage | abstract-shape | icon-set | hand-drawn | geometric",
"treatment": "Traitement appliqué aux images — ex: 'duotone avec accent + dark, contrast élevé, coins arrondis 12px, ombre portée 0 8px 32px rgba(0,0,0,0.4)'",
"composition": "Comment les images sont composées dans le layout — ex: 'Images en plein écran avec overlay gradient dark 60%, texte par-dessus en blanc'",
"promptTemplates": [
{
"category": "Ce type d'image (hero, background, personnage, objet, etc.)",
"style": "Description DÉTAILLÉE du style visuel (matière, éclairage, palette, rendu)",
"promptTemplate": "Le prompt GÉNÉRIQUE (sans sujet spécifique) pour reproduire ce style — ex: 'Grayscale editorial portrait of [SUJET], studio lighting, high contrast, clean cutout white background, ultra sharp, monochrome --ar 2:3'. Le [SUJET] sera remplacé par le contenu de chaque scène.",
"placement": "Où et comment dans le layout — ex: 'Z2, centré, 400-500px, avec filter grayscale(100%)'"
}
],
"promptHint": "Résumé du style pour les prompts AI — ex: 'Corporate flat illustration, personnages géométriques sans visage, palette limitée 3 couleurs, style Notion/Stripe'",
"nbImagesPerAnimation": "Combien d'images AI cette esthétique nécessite — typiquement 3-5 pour 3 scènes"
},
"moodKeywords": ["5-7 mots clés d'ambiance précis"],
"bestFor": ["types de contenu où ce style brille"]
}
}
Pour chaque animation, demande-toi : "Avec cette description, est-ce que je peux écrire le code Remotion sans revoir la vidéo ?"
Si la réponse est non → ajoute plus de détail.
Exemples de ce qui est INSUFFISANT vs SUFFISANT :
❌ "Icons scale in with bounce"
✅ "Chaque icône scale de 0→1 avec spring(stiffness:200, damping:8, mass:0.5), stagger de 3 frames entre chaque, overshoot à ~1.15 avant de revenir à 1.0, depuis le centre du canvas"
❌ "Text slides up"
✅ "Le mot 'GROWTH' slide de Y:+300px à Y:0 avec ease-out-back (overshoot -20px), opacity 0→1 sur les 3 premières frames, motionBlur vertical pendant le mouvement, fontSize ~120px en Inter 900 uppercase, color #ffffff"
❌ "Dark background with glow"
✅ "Background #0a0a0a uni. Radial gradient centered at (540, 780): accent color #d4382c à 15% opacity, radius 450px, pulsating opacity entre 12%-18% à freq 0.06. Ghost text '90%' en arrière-plan à fontSize 500px, opacity 0.04, position (-80, 100), rotation -5deg, blur 4px"
Le name (et daTemplate.name) est un nom COURT et ÉVOCATEUR que tu inventes. PAS le nom du fichier.
Exemples de bons noms :
Le nom doit refléter l'ESSENCE VISUELLE du style, pas le contenu.
mkdir -p references/pinterest/analyses
Fichier : references/pinterest/analyses/[name-en-kebab-case].json
Exemple : le style "Neon Pulse" → references/pinterest/analyses/neon-pulse.json
rm -rf "$TMPDIR"
allSi $ARGUMENTS[0] est all ou absent :
references/pinterest/references/pinterest/analyses/sourceFile dans les JSON existants)Pour chaque vidéo analysée, affiche :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎬 [name] — [sourceFile]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[overview]
QUOI : [type] — [elements listés]
[N] scènes détaillées, [N] éléments animés documentés
COMMENT :
Rythme : [rhythm.type] — [rhythm.bpm] changements/s
Caméra : [camera.type] — wander ±[X]px, shake sur impacts
Transitions : [type dominant] — [durationFrames]f overlap
Effets : [liste des effets actifs avec intensités]
POURQUOI : [mood]
Force principale : [forces[0]]
DA-Template : "[daTemplate.name]"
Palette : ■ dark ■ light ■ accent ■ subtle
Typo primaire : [fontStyle.primary.description] — [sizes.hero] hero
Typo secondaire : [fontStyle.secondary.description]
Layers : [N] couches avec parallax
Signatures : [signatureAnimations names]
Best for : [bestFor]
→ Sauvé : references/pinterest/analyses/[kebab-name].json
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ [N] vidéo(s) analysée(s) — [N] DA-templates créés
Analyses : references/pinterest/analyses/
Templates disponibles :
- [name1] ([sourceFile1])
- [name2] ([sourceFile2])
...
Pour créer un design à partir d'un template :
→ /motion-design [nom-design] [copier le style de "DA-template name"]