Communitygithub.com

ilya-makarov-dev/Reframe

Créez des compositions vidéo, des animations, des cartons-titres, des incrustations, des sous-titres, des voix off, des visuels réactifs à l'audio et des transitions de scène en HyperFrames HTML. Utilisez-le pour toute demande de contenu vidéo HTML, ajout de sous-titres synchronisés, génération de narration par synthèse vocale, animation réactive à la musique (syncope de battement, lueur, pulsation), surlignage de texte animé (marqueurs, cercles dessinés à la main, lignes d'éclatement, gribouillis, esquisses) ou transitions entre scènes (fondus, volets, révélations, shaders).

Qu'est-ce que Reframe ?

Reframe est une compétence d'agent IA spécialisée dans la création de compositions vidéo basées sur HyperFrames HTML. Elle permet de générer des animations, des cartons-titres, des incrustations, des sous-titres synchronisés avec l'audio, des voix off par synthèse vocale, des visuels réactifs à la musique (syncope de battement, lueur, pulsation), ainsi que des transitions de scène élaborées (fondus, volets, révélations, shaders). Elle est conçue pour les agents comme Claude Code, Cursor, Codex et autres environnements de développement. La compétence impose une approche structurée : définir d'abord une identité visuelle via un fichier DESIGN.md, puis appliquer une mise en page statique avant toute animation. Elle utilise GSAP pour les animations et suit un contrat de timeline strict (paused: true, enregistrement obligatoire dans window.__timelines). Les transitions entre scènes sont obligatoires et les animations de sortie sont interdites sauf pour la dernière scène. Elle s'intègre avec hyperframes-cli pour les commandes d'initialisation, d'aperçu, de rendu, de transcription et de synthèse vocale.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ilya-makarov-dev/Reframe/tree/HEAD/.claude/skills/hyperframes

Demander à votre IA préférée

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

Aperçu

Depuis le README du skill

Documentation

HyperFrames

L'HTML est la source de vérité pour la vidéo. Une composition est un fichier HTML avec des attributs data-* pour le timing, une timeline GSAP pour l'animation, et du CSS pour l'apparence. Le framework gère la visibilité des clips, la lecture des médias et la synchronisation de la timeline.

Approche

Avant d'écrire du HTML, réfléchissez à un niveau élevé :

  1. Quoi — que doit vivre le spectateur ? Identifiez l'arc narratif, les moments clés et les battements émotionnels.
  2. Structure — combien de compositions, lesquelles sont des sous-compositions vs en ligne, quelles pistes transportent quoi (vidéo, audio, incrustations, sous-titres).
  3. Timing — quels clips déterminent la durée, où se placent les transitions, quel est le rythme.
  4. Mise en page — construisez d'abord l'état final. Voir "Mise en page avant animation" ci-dessous.
  5. Animer — ajoutez ensuite le mouvement en utilisant les règles ci-dessous.

Pour les petites modifications (corriger une couleur, ajuster le timing, ajouter un élément), passez directement aux règles.

Porte d'Identité Visuelle

Vérifiez dans cet ordre :

  1. DESIGN.md existe dans le projet ? → Lisez-le. Utilisez ses couleurs, polices, règles de mouvement et contraintes "À NE PAS FAIRE" exactes.
  2. visual-style.md existe ? → Lisez-le. Appliquez son style_prompt_full et ses champs structurés. (Note : visual-style.md est un fichier propre au projet. visual-styles.md est la bibliothèque de styles avec 8 préréglages nommés — des fichiers différents.)
  3. L'utilisateur a nommé un style (ex. "Swiss Pulse", "dark and techy", "luxury brand") ? → Lisez visual-styles.md pour les 8 préréglages nommés. Générez un DESIGN.md minimal avec : ## Style Prompt (un paragraphe), ## Colors (3-5 valeurs hex avec rôles), ## Typography (1-2 familles de polices), ## What NOT to Do (3-5 anti-patrons).
  4. Rien de tout cela ? → Posez 3 questions avant d'écrire le HTML :
    • Quelle est l'ambiance ? (explosive / cinématographique / fluide / technique / chaotique / chaleureuse)
    • Toile claire ou sombre ?
    • Y a-t-il des couleurs de marque, des polices ou des références visuelles spécifiques ? Générez ensuite un DESIGN.md minimal à partir des réponses.

Chaque composition doit faire remonter sa palette et sa typographie à un DESIGN.md, visual-style.md ou à une directive explicite de l'utilisateur. Si vous utilisez #333, #3b82f6 ou Roboto — vous avez sauté cette étape.

Pour les valeurs par défaut de mouvement, les tailles, les motifs d'entrée et l'assouplissement — suivez house-style.md. Le style maison gère COMMENT les choses bougent. Le DESIGN.md gère À QUOI elles ressemblent.

Mise en page avant animation

Positionnez chaque élément là où il doit être à son moment le plus visible — l'image où il est complètement entré, correctement placé, et pas encore en train de sortir. Écrivez cela en HTML+CSS statique d'abord. Pas encore de GSAP.

Pourquoi c'est important : Si vous positionnez les éléments à leur état de départ animé (hors écran, échelle à 0, opacité 0) et les animez vers où vous pensez qu'ils devraient atterrir, vous devinez la mise en page finale. Les chevauchements sont invisibles jusqu'au rendu de la vidéo. En construisant l'état final en premier, vous pouvez voir et corriger les problèmes de mise en page avant d'ajouter du mouvement.

Le processus

  1. Identifiez l'image héroïque de chaque scène — le moment où le plus d'éléments sont simultanément visibles. C'est la mise en page que vous construisez.
  2. Écrivez le CSS statique pour cette image. Le conteneur .scene-content DOIT remplir toute la scène avec width: 100%; height: 100%; padding: Npx; avec display: flex; flex-direction: column; gap: Npx; box-sizing: border-box. Utilisez le padding pour pousser le contenu vers l'intérieur — JAMAIS position: absolute; top: Npx sur un conteneur de contenu. Les conteneurs de contenu en position absolue débordent lorsque le contenu est plus grand que l'espace restant. Réservez position: absolute uniquement pour les éléments décoratifs.
  3. Ajoutez les entrées avec gsap.from() — animez DEPUIS hors écran/invisible VERS la position CSS. La position CSS est la vérité terrain ; l'interpolation décrit le parcours pour y arriver.
  4. Ajoutez les sorties avec gsap.to() — animez VERS hors écran/invisible DEPUIS la position CSS.

Exemple

/* scene-content remplit la scène, le padding positionne le contenu */
.scene-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 120px 160px;
  gap: 24px;
  box-sizing: border-box;
}
.title {
  font-size: 120px;
}
.subtitle {
  font-size: 42px;
}
/* Le conteneur remplit toute taille de scène (1920x1080, 1080x1920, etc.).
   Le padding positionne le contenu. Flex + gap gère l'espacement. */

MAUVAIS — dimensions codées en dur et positionnement absolu :

.scene-content {
  position: absolute;
  top: 200px;
  left: 160px;
  width: 1920px;
  height: 1080px;
  display: flex; /* ... */
}
// Étape 3 : Animez VERS ces positions
tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
tl.from(".logo", { scale: 0.8, opacity: 0, duration: 0.4, ease: "power2.out" }, 0.3);

// Étape 4 : Animez DEPUIS ces positions
tl.to(".title", { y: -40, opacity: 0, duration: 0.4, ease: "power2.in" }, 3);
tl.to(".subtitle", { y: -30, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.1);
tl.to(".logo", { scale: 0.9, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.2);

Quand les éléments partagent l'espace dans le temps

Si l'élément A sort avant que l'élément B n'entre dans la même zone, les deux doivent avoir des positions CSS correctes pour leurs images héroïques respectives. L'ordre de la timeline garantit qu'ils ne coexistent jamais visuellement — mais si vous sautez l'étape de mise en page, vous ne détecterez pas le cas où ils se chevauchent accidentellement en raison d'une erreur de timing.

Ce qui compte comme chevauchement intentionnel

Les effets en couches (lueur derrière le texte, éléments d'ombre, motifs d'arrière-plan) et les conceptions en piles z (piles de cartes, couches de profondeur) sont intentionnels. L'étape de mise en page consiste à détecter les chevauchements non intentionnels — deux titres atterrissant l'un sur l'autre, une statistique couvrant une étiquette, du contenu débordant du cadre.

Attributs de données

Tous les clips

AttributRequisValeurs
idOuiIdentifiant unique
data-startOuiSecondes ou référence d'ID de clip ("el-1", "intro + 2")
data-durationRequis pour img/div/compositionsSecondes. La vidéo/audio utilise par défaut la durée du média.
data-track-indexOuiEntier. Les clips de la même piste ne peuvent pas se chevaucher.
data-media-startNonDécalage de coupe dans la source (secondes)
data-volumeNon0-1 (par défaut 1)

data-track-index n'affecte pas la superposition visuelle — utilisez CSS z-index.

Clips de composition

AttributRequisValeurs
data-composition-idOuiID de composition unique
data-startOuiTemps de début (composition racine : utilisez "0")
data-durationOuiPrime sur la durée de la timeline GSAP
data-width / data-heightOuiDimensions en pixels (1920x1080 ou 1080x1920)
data-composition-srcNonChemin vers un fichier HTML externe

Structure de composition

Les sous-compositions chargées via data-composition-src utilisent un wrapper <template>. Les compositions autonomes (le index.html principal) n'utilisent PAS de <template> — elles placent la div data-composition-id directement dans <body>. Utiliser <template> sur un fichier autonome cache tout contenu au navigateur et casse le rendu.

Structure de sous-composition :

<template id="ma-comp-template">
  <div data-composition-id="ma-comp" data-width="1920" data-height="1080">
    <!-- contenu -->
    <style>
      [data-composition-id="ma-comp"] {
        /* styles limités */
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
    <script>
      window.__timelines = window.__timelines || {};
      const tl = gsap.timeline({ paused: true });
      // interpolations...
      window.__timelines["ma-comp"] = tl;
    </script>
  </div>
</template>

Chargement dans la racine : <div id="el-1" data-composition-id="ma-comp" data-composition-src="compositions/ma-comp.html" data-start="0" data-duration="10" data-track-index="1"></div>

Vidéo et audio

La vidéo doit être muted playsinline. L'audio est toujours un élément <audio> séparé :

<video
  id="el-v"
  data-start="0"
  data-duration="30"
  data-track-index="0"
  src="video.mp4"
  muted
  playsinline
></video>
<audio
  id="el-a"
  data-start="0"
  data-duration="30"
  data-track-index="2"
  src="video.mp4"
  data-volume="1"
></audio>

Contrat de timeline

  • Toutes les timelines commencent { paused: true } — le lecteur contrôle la lecture
  • Enregistrez chaque timeline : window.__timelines["<id-de-composition>"] = tl
  • Le framework imbrique automatiquement les sous-timelines — ne les ajoutez PAS manuellement
  • La durée vient de data-duration, pas de la longueur de la timeline GSAP
  • Ne créez jamais d'interpolations vides pour définir la durée

Règles (Non Négociables)

Déterministe : Pas de Math.random(), Date.now() ou de logique basée sur le temps. Utilisez un PRNG ensemencé si vous avez besoin de valeurs pseudo-aléatoires (ex. mulberry32).

GSAP : Animez uniquement les propriétés visuelles (opacity, x, y, scale, rotation, color, backgroundColor, borderRadius, transformations). N'animez PAS visibility, display et n'appelez PAS video.play()/audio.play().

Conflits d'animation : N'animez jamais la même propriété sur le même élément à partir de plusieurs timelines simultanément.

Pas de repeat: -1 : Les timelines à répétition infinie cassent le moteur de capture. Calculez le nombre exact de répétitions à partir de la durée de la composition : repeat: Math.ceil(duration / cycleDuration) - 1.

Construction synchrone de timeline : Ne construisez jamais de timelines à l'intérieur de async/await, setTimeout ou de Promesses. Le moteur de capture lit window.__timelines de manière synchrone après le chargement de la page. Les polices sont intégrées par le compilateur, donc elles sont disponibles immédiatement — pas besoin d'attendre le chargement des polices.

Ne faites jamais :

  1. Oublier l'enregistrement window.__timelines
  2. Utiliser la vidéo pour l'audio — toujours vidéo muette + <audio> séparé
  3. Nicher la vidéo dans une div temporisée — utilisez un wrapper non temporisé
  4. Utiliser data-layer (utilisez data-track-index) ou data-end (utilisez data-duration)
  5. Animer les dimensions de l'élément vidéo — animez une div wrapper
  6. Appeler play/pause/seek sur les médias — le framework possède la lecture
  7. Créer un conteneur de premier niveau sans data-composition-id
  8. Utiliser repeat: -1 sur une timeline ou une interpolation — toujours des répétitions finies
  9. Construire des timelines de manière asynchrone (dans async, setTimeout, Promise)
  10. Utiliser gsap.set() sur des éléments de clip de scènes ultérieures — ils n'existent pas dans le DOM au chargement de la page. Utilisez plutôt tl.set(selector, vars, timePosition) dans la timeline au moment ou après le data-start du clip.
  11. Utiliser <br> dans le texte du contenu — les sauts de ligne forcés ne tiennent pas compte de la largeur de police réellement rendue. Le texte qui se retourne naturellement + un <br> produit un saut supplémentaire indésirable, causant un chevauchement. Laissez le texte se retourner via max-width à la place. Exception : les titres d'affichage courts où chaque mot est délibérément sur sa propre ligne (ex. "THE\nIMMORTAL\nGAME" à 130px).

Transitions de scène (Non Négociables)

Toute composition multi-scène DOIT suivre TOUTES ces règles. En violer une seule rend la composition cassée.

  1. Utilisez TOUJOURS des transitions entre les scènes. Pas de coupes franches. Aucune exception.
  2. Utilisez TOUJOURS des animations d'entrée sur chaque scène. Chaque élément s'anime VERS l'intérieur via gsap.from(). Aucun élément ne peut apparaître complètement formé. Si une scène a 5 éléments, elle a besoin de 5 interpolations d'entrée.
  3. N'utilisez JAMAIS d'animations de sortie sauf sur la scène finale. Cela signifie : PAS de gsap.to() qui anime l'opacité à 0, y hors écran, l'échelle à 0, ou toute autre animation "vers l'extérieur" avant qu'une transition ne se déclenche. La transition EST la sortie. Le contenu de la scène sortante DOIT être entièrement visible au moment où la transition commence.
  4. Scène finale uniquement : La dernière scène peut estomper des éléments (ex. fondu au noir). C'est la SEULE scène où gsap.to(..., { opacity: 0 }) est autorisé.

MAUVAIS — animation de sortie avant la transition :

// INTERDIT — cela vide la scène avant que la transition puisse l'utiliser
tl.to("#s1-title", { opacity: 0, y: -40, duration: 0.4 }, 6.5);
tl.to("#s1-subtitle", { opacity: 0, duration: 0.3 }, 6.7);
// la transition se déclenche sur une image vide

BON — entrée uniquement, la transition gère la sortie :

// Animations d'entrée de la scène 1
tl.from("#s1-title", { y: 50, opacity: 0, duration: 0.7, ease: "power3.out" }, 0.3);
tl.from("#s1-subtitle", { y: 30, opacity: 0, duration: 0.5, ease: "power2.out" }, 0.6);
// PAS d'interpolations de sortie — la transition à 7,2 s gère le changement de scène
// Animations d'entrée de la scène 2
tl.from("#s2-heading", { x: -40, opacity: 0, duration: 0.6, ease: "expo.out" }, 8.0);

Garde-fous d'animation

  • Décalez la première animation de 0,1 à 0,3 s (pas à t=0)
  • Variez les assouplissements entre les interpolations d'entrée — utilisez au moins 3 assouplissements différents par scène
  • Ne répétez pas un motif d'entrée dans une scène
  • Évitez les dégradés linéaires plein écran sur fonds sombres (crénelage H.264 — utilisez radial ou uni + lueur localisée)
  • Titres de 60px+, corps de 20px+, étiquettes de données de 16px+ pour la vidéo rendue
  • font-variant-numeric: tabular-nums sur les colonnes de nombres

Lorsqu'aucune visual-style.md ou direction d'animation n'est fournie, suivez house-style.md pour les valeurs par défaut esthétiques.

Typographie et ressources

  • Polices : Écrivez simplement le font-family souhaité en CSS — le compilateur intègre automatiquement les polices prises en charge. Si une police n'est pas prise en charge, le compilateur prévient.
  • Ajoutez crossorigin="anonymous" aux médias externes
  • Pour...

[suite tronquée pour la traduction]

Skills associés