Motion design (version HyperFrames)
Les documents HyperFrames vous apprennent l'API ; ce fichier s'occupe du goût. Les chiffres ci-dessous proviennent d'un projet réel mis en ligne. Traitez-les comme des valeurs par défaut : vous pouvez vous en écarter, mais ce doit être intentionnel, pas par inadvertance.
Adapté du skill
motion-designdewhaleyxbt/claude-motion(MIT, voirLICENSEdans le même dossier). L'original ciblait Remotion ; cette version est réécrite pour HyperFrames (HTML + GSAP) et inclut des règles de composition pour le chinois traditionnel. Les sections marquées « (ajout de cette version) » ne font pas partie du contenu original.
Répartition avec les skills HyperFrames officiels (ajout de cette version)
Cette machine dispose également des skills HyperFrames officiels de HeyGen (hyperframes, hyperframes-core, hyperframes-animation, etc.). La répartition est la suivante :
- Les skills officiels s'occupent du « comment faire » : structure du projet, attributs
data-*, écriture de l'API, routage des flux, composants prêts à l'emploi du registre. En cas de conflit avec ce fichier, les règles officielles prévalent. - Ce fichier s'occupe du « goût » : easing, rythme, temps de pause, polices, couleurs, composition chinoise. Lorsque vous utilisez les règles / blueprints du skill officiel
hyperframes-animation, les valeurs de temps et d'easing de ce fichier restent les valeurs par défaut. - Vérification : toujours via
review-loop, qui inclut déjà la vérification officiellehyperframes check.
0. Règles strictes d'HyperFrames (ajout de cette version)
Le non-respect de ces règles entraînera des scintillements, des décalages ou des résultats variables lors du rendu :
-
Le temps est déterminé par le HTML : chaque scène est un élément avec
class="clip", utilisantdata-startetdata-durationpour le positionner sur la timeline. L'élément racine doit avoirdata-composition-idet undata-durationexplicite. -
Les animations sont gérées par GSAP :
gsap.timeline({ paused: true }), enregistrée danswindow.__timelines["<composition-id>"], avec une clé égale àdata-composition-id. -
Chaque tween important reçoit une position explicite (troisième paramètre) ; utilisez
fromTo()si les deux extrémités sont importantes, car le rendu cherchera par sauts. -
Ne modifiez que
transformetopacity; ne modifiez pastop/left/width/heightde manière répétée. -
Interdits :
transition/@keyframesCSS,Date.now(),requestAnimationFrame,setTimeout,Math.random()sans graine, ressources chargées pendant le rendu. -
Ne lisez, ne mettez en pause, ne cherchez pas de contenu audio/vidéo par script, et n'affichez/ne cachez pas de clip en fonction du temps par script. Tout cela est géré par les attributs de données. Pour déplacer une vidéo, déplacez l'élément conteneur externe.
-
L'aléatoire doit toujours utiliser une fonction avec graine :
function rand(seed) { let t = (seed += 0x6D2B79F5); t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }
1. Temps centralisé en un seul endroit
-
Chaque battement est un instant nommé (en secondes), regroupé par scène (
s1,s2...), écrit danstimeline.jsà la racine du projet :window.TL = { s1: { start: 0, title: 0.3, items: [1.2, 1.45, 1.7], exit: 3.6 }, s2: { start: 3.4, drawOn: 3.5, hook: 5.2, end: 8 }, };Dans
index.html, chargez d'abord<script src="timeline.js"></script>avant tous les scripts de composition. -
Les paramètres de position GSAP sont toujours pris à partir de
TL(TL.s1.title,TL.s1.exit + 0.05pour les expressions relatives) ; n'écrivez pas de secondes en dur dans les scènes. -
Les attributs
data-start/data-durationdes clips de scène doivent correspondre aux limites de scène dansTL. Lors du ré-étalonnage temporel, modifiez d'abordtimeline.js, puis synchronisez ces deux attributs. -
Les effets sonores et la narration sont placés via
<audio data-start="…">sur les mêmes battements. Les temps de capture d'écran dereview-loopsont également pris dansTL, donc l'image, le son et la vérification bougent ensemble. -
Toutes les images sont déterminées uniquement par le temps, voir section 0.
2. Easing
Les quatre courbes de l'original sont reconstruites avec précision dans GSAP en utilisant CustomEase. Chargez gsap@3/dist/CustomEase.min.js, puis enregistrez avec gsap.registerPlugin(CustomEase) :
CustomEase.create("enter", "0.16,1,0.3,1"); // easeOut
CustomEase.create("exit", "0.6,0,0.9,0.35"); // easeIn
CustomEase.create("move", "0.65,0,0.35,1"); // easeInOut
CustomEase.create("land", "0.55,0,0.2,1.12"); // overshoot
| Courbe | Utilisation | Nom intégré le plus proche |
|---|---|---|
enter = bezier(0.16, 1, 0.3, 1) | Entrée, révélation, tout « arrivée » | expo.out (presque identique) |
exit = bezier(0.6, 0, 0.9, 0.35) | Sortie : rapide, sans traîner | Environ power3.in |
move = bezier(0.65, 0, 0.35, 1) | Mouvement entre deux états (retournement, arrêt, transformation) | power2.inOut (exactement identique) |
land = bezier(0.55, 0, 0.2, 1.12) | Valeurs qui « s'installent » (curseur s'arrêtant à une certaine position) | Pas de bon équivalent intégré, utilisez CustomEase |
ease: "none" (linéaire) n'est utilisé que pour les mouvements continus : rotation, dérive, particules, aiguille des secondes.
Pour qu'une animation suive une autre valeur (par exemple, un sous-titre suivant la position d'un curseur), utilisez le même tween pour piloter un objet proxy et dériver dans onUpdate ; ne lui donnez pas une autre horloge indépendante.
3. Élasticité
L'original utilisait des ressorts physiques de Remotion ; GSAP n'a pas de physique de ressort. Le tableau ci-dessous montre les approximations choisies (ajout de cette version, pas les chiffres originaux). Après le rendu, vérifiez la sensation avec review-loop :
| Sensation | Configuration GSAP | Utilisation |
|---|---|---|
| Arrivée par défaut | back.out(1.2), 0.6 s | Entrée UI générale |
| Lourd, stable | power3.out, 0.8–1.0 s | Grands panneaux, inversions |
| Bouton cranté | back.out(1.7), 0.35 s | Sauts de contrôle à une certaine position |
| Éjection | back.out(2.2), 0.45 s | Annotations, badges, points de succès |
| Accent élastique | elastic.out(1, 0.4), 0.9 s | Moment culminant, utilisé une seule fois par vidéo |
Les éléments qui ont une sensation physique (UI, objets) utilisent l'élasticité ; le texte et les mouvements de type caméra utilisent les courbes de Bézier.
4. Rythme
- Échelonnement : pour les mots anglais, environ 0.09 s ; pour les caractères chinois un par un, environ 0.04–0.05 s, par mot chinois environ 0.09 s (la partie chinoise est un ajout de cette version) ; pour les éléments de liste et les étiquettes, environ 0.2–0.25 s ; pour les anneaux et les points, environ 0.06 s.
- Révélation de texte : environ 0.8 s, avec un masque : le conteneur extérieur en
overflow: hidden, l'intérieur enyPercent: 100 → 0, plus une légère rotation (rotation: 3 → 0). - La sortie est environ la moitié de l'entrée (0.35–0.55 s contre 0.7–1.25 s), en utilisant la courbe
exit. - Les scènes doivent se chevaucher : la scène suivante commence à se dessiner avant que la précédente ne soit complètement sortie (par exemple,
s2.drawOnà 4.02 s est avants1.flipEndà 4.4 s). Un espace blanc dur donne l'impression de « chargement ». - Dactylographie : chaque caractère environ 0.035 s ; en inactivité, le curseur clignote à environ 2.4 Hz (avec
stepsousetdisposés sur la timeline, pas avec un minuteur). - Pause de lecture : chaque état à lire doit s'arrêter après son installation. Les phrases courtes : au moins 1 s ; pour plus de trois mots, ajoutez environ 0.25 s par mot supplémentaire ; pour le chinois, ajoutez environ 0.25 s tous les 4 caractères (ajout de cette version). La dernière phrase finale : au moins 2 s. La version 22 secondes de l'original existait parce que la version 15 secondes faisait défiler les mots trop vite : en cas de doute, pause plus longue, moins de mouvement.
5. Polices
- Maximum trois familles : un sérif pour l'affichage, un sans-sérif pour l'interface, un chasse fixe (pour les étiquettes, les invites, les chiffres).
- Anglais (original) : Instrument Serif / Inter / JetBrains Mono.
- Chinois traditionnel (ajout de cette version) : Noto Serif TC / Noto Sans TC, avec JetBrains Mono pour les chiffres et les étiquettes. Les fichiers de police sont placés dans
assets/fonts/du projet, chargés avec@font-face, ne dépendant pas des polices système (différentes sur un autre ordinateur).
- Le texte d'affichage en anglais doit être grand (environ 138 px sur un canevas de 1080 de large), avec un crénage serré (
-0.02em),line-height: 1. - Le texte d'affichage en chinois (ajout de cette version) : environ 96–120 px pour une largeur de 1080, pas plus d'environ 12 caractères par ligne, crénage de
0à0.02em(pas de crénage négatif en chinois),line-height: 1.15–1.25. - Un point fort par ligne : en anglais, utilisez un mot en italique avec une couleur d'accentuation ; en chinois, pas de véritable italique, utilisez une couleur d'accentuation et du gras pour porter le point fort (ajout de cette version).
- Étiquettes à chasse fixe : en majuscules,
letter-spacing: 0.2–0.24em, couleur atténuée. Ce ne sont que des décorations ; ce que le spectateur doit absolument lire doit être grand. - Test mobile : à 360 px de large (taille réelle vue dans les flux sociaux), les informations clés doivent encore être lisibles. Vérifiez avec la planche contact.
6. Palette de couleurs
- (Ajout de cette version) La vidéo entière est définie par trois couleurs, comme une maquette de présentation, décidées par l'utilisateur : couleur de fond
bg, couleur principalefg(pour le texte et les lignes), couleur d'accentuationaccent, écrites danstheme.jsondu projet, appliquées à l'aide du skillmotion-explainer(ou de sa version améliorée par imagesmotion-explainer-images) viatheme.py. La couleur d'accentuation est réservée aux « réponses, conclusions, chiffres clés, cartes de chapitre ». - Le nuancier est défini comme des variables CSS
:root(--bg,--ink,--muted,--accent...). N'ajoutez pas de nouveaux codes de couleur dans les scènes. - Il n'y a qu'une seule couleur d'accentuation, et elle a du sens : la chose qui change, la réponse, le gagnant. Si tout est accentué, alors rien ne l'est.
- Les halos sont pilotés par l'état, pas par le temps (
glow = effort) : la lumière doit raconter une histoire.
7. Texture : rien n'est complètement immobile
- Grain de film : superposez un filtre SVG
feTurbulence, opacité d'environ 0.09, changez laseedtoutes les deux images (disposée sur la timeline avecset, la graine calculée à partir du numéro d'image). - Vignettage + grille de points, dérive de quelques pixels par seconde : dégradé radial pour le vignettage, une tween linéaire traversant toute la vidéo pour la grille.
- « Tremblement de ligne » dessiné à la main (
feTurbulence+feDisplacementMap, également avec changement de graine toutes les deux images) : utilisé pour une sensation d'esquisse, d'état peu finalisé, disparaît lorsque la qualité augmente. - Les éléments inactifs doivent respirer : horloge qui tourne, curseur qui clignote, rotation lente.
8. Continuité et transitions
- Préférez la continuité des objets à une coupure franche. Dans l'original, la barre de notification, les étincelles et le curseur traversent les scènes et changent de rôle : c'est la différence entre « conçu » et « bricolé ». Dans HyperFrames, les objets inter-scènes sont placés dans la composition racine, pas à l'intérieur d'une scène particulière.
- Chaque transition doit être portée par un objet sur l'écran (les cinq points de résultat se fondent en un seul, puis se transforment en halo). N'utilisez pas de transitions de type wipe standard.
- Utilisez la vitesse : les traînées, les compressions sont dérivées de la « différence de valeur entre cette image et la précédente », ne les simulez pas artificiellement.
- Chaque vidéo a un moment culminant (halo + impact). Construisez-y progressivement, ne l'utilisez pas trop tôt.
9. Anti-patrons
- Tout fondu en même temps, ou tout avec la même durée.
- Utilisation d'un easing linéaire pour des choses qui démarrent et s'arrêtent.
- Texte qui bouge encore alors qu'il devrait être lu.
- Plus d'un point focal dans une même image.
- Contenu à moins d'environ 60 px du bord de l'écran (zone de sécurité), sauf si intentionnellement coupé.
- Première image vide ou entièrement noire : lors de la lecture automatique en sourdine sur les réseaux sociaux, la première image est la vignette.
- (Ajout de cette version) Contrôle de la lecture audio/vidéo ou de l'affichage des clips dans un script, utilisation d'animations CSS, utilisation d'aléatoire sans graine, voir section 0.
Flux de travail
- Écrivez d'abord les battements dans
timeline.js(storyboard avec des chiffres), confirmez le rythme avec l'utilisateur avant de commencer. - Créez le projet avec
hyperframes_initde kinocut ; chaque scène est une composition danscompositions/, les composants partagés et les objets inter-scènes sont placés dansindex.html. - Après chaque modification significative, exécutez le skill
review-loop. - Traitez le son après avoir verrouillé les temps de l'image : les effets sonores et la musique de fond sont synchronisés sur les battements de
TLavec<audio data-start>. Confiez les accents et l'émotion de la narration en chinois à l'oreille de l'utilisateur, ne les remplacez pas par des scores ASR ou de similarité (ajout de cette version).