Communitygithub.com

YahyaLendani/motionbrief

Créez des motion graphics et des vidéos courtes à partir d'HTML ou de React : cartes-titres, logos animés, typographie cinétique, compteurs, révélations de statistiques, tiers inférieurs, superpositions transparentes, montages de fonctionnalités. Compile une demande en langage naturel en un brief validé, puis le rend ; transforme un brief en plusieurs vidéos. Couvre HyperFrames (HTML + GSAP, avec auto-installation, Apache 2.0) et Remotion (React + TypeScript). Utilisez-le lorsqu'on vous demande de générer, animer, construire ou rendre une vidéo, un motion graphic, une animation ou une superposition ; pour créer une vidéo de lancement, un jingle ou une carte ; pour porter une composition entre Remotion et HyperFrames ; ou pour corriger un mouvement qui semble bon marché, saccadé, lent ou glissant.

Qu'est-ce que motionbrief ?

Ce skill permet à un agent IA de transformer une simple requête textuelle — comme « crée un logo animé de 6 secondes pour Inkwell » — en une vidéo de motion graphics complète, sans que l'utilisateur ait à rédiger un brief technique. L'agent compile d'abord la demande en un fichier `brief.json` structuré (durée, dimensions, images par seconde, rythme des scènes, couleurs, police, etc.), puis génère le code de composition à partir de modèles validés. Deux frameworks sont supportés : HyperFrames (un simple fichier HTML avec CSS et une timeline GSAP en pause) et Remotion (composants React avec TypeScript). L'outil effectue des vérifications statiques et dynamiques pour garantir que le timing, le texte et les transitions respectent le brief, et il capture des images clés pour une inspection visuelle. Le rendu final produit une vidéo avec ou sans bande sonore, et le processus peut être itéré en modifiant seulement le fichier brief. Le skill est conçu pour être utilisé dans des environnements comme Claude Code, Cursor ou Codex, où l'agent peut interpréter le markdown de la compétence et exécuter les scripts locaux. Il est particulièrement adapté pour la création rapide de contenu marketing, de présentations animées ou de prototypes vidéo.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/YahyaLendani/motionbrief-claude-skills/tree/main/skills/motionbrief

Demander à votre IA préférée

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

Documentation

Motion Graphics

Générez une vidéo en écrivant une page web que le moteur de rendu parcourt image par image. Les deux voies ci-dessous font la même chose ; la différence réside dans ce que vous écrivez.

  • HyperFrames — un fichier HTML, du CSS pour l'apparence, une timeline GSAP en pause pour l'animation. node scripts/hf.mjs exécute la version épinglée et l'installe une fois depuis un fichier de verrouillage validé. Apache 2.0.
  • Remotion — des composants React. useCurrentFrame() renvoie la trame, vous faites le calcul. Mature, typé, et sous licence gratuite uniquement jusqu'à trois personnes.

Chargez la référence correspondante avant d'écrire le code de composition. Les règles du framework ne sont pas devinables et la plupart des échecs sont silencieux : un fichier HyperFrames qui n'enregistre jamais sa timeline produit une image fixe sans message d'erreur.


Le chemin facile

L'utilisateur décrit ce qu'il veut en termes simples. Il n'écrit jamais de brief, de cahier des charges ou de feuille de rythme — Claude le compile.

/motion un logo animé percutant de 6 secondes pour Inkwell

Voilà toute l'entrée. En dessous :

  1. Compile la demande en brief.json — durée, taille, images par seconde, rythme avec les timings, copie textuelle, easings, palette, et une liste assumptions. Chaque manque est comblé par une valeur par défaut provenant du tableau dans references/brief.md ; rien n'est laissé indéfini et rien n'est remis en question.
  2. Affiche le résumé compact (un tableau, ~12 lignes) et construit dans le même tour de parole. Pas de validation intermédiaire.
  3. Construit à partir du modèle, valide, rend, examine les images.

L'itération se fait ensuite par modification d'un champ, pas par reconstruction. « Rends-le plus percutant » modifie feel.ease et deux durées ; le code ne bouge pas sauf si kind ou motion change.

Le brief est l'artefact qui rend tout cela économique. Il vit sur le disque à côté de la composition, donc une révision est un diff, et un nouveau rendu est une seule commande.


Choix de la voie

SignalVoie
Nouvelle construction, aucun framework nomméHyperFrames
HTML/CSS/GSAP/Lottie existant à réutiliserHyperFrames
Pas de node_modules, pas d'étape de build souhaitéeHyperFrames
Équipe de plus de trois personnesHyperFrames (licence)
L'utilisateur nomme Remotion, ou le dépôt est React/TSRemotion
A besoin d'un système de design, d'une bibliothèque de graphiques ou de composants complexesRemotion
Portage d'un projet Remotion existantRemotion (le portage coûte plus qu'il ne rapporte)

Lorsque l'utilisateur nomme les deux, construisez en HyperFrames et dites en une ligne que le portage Remotion est disponible sur demande. Deux constructions complètes de la même pièce est du travail inutile sauf si une comparaison a été demandée.


La boucle

1. Compiler le brief

Transformez la demande en brief.json avant d'écrire du code. Le schéma, la grammaire kind/motion, le tableau des valeurs par défaut et les leviers d'itération se trouvent dans references/brief.md.

node scripts/brief.mjs brief.json          # valider + tableau récapitulatif
node scripts/brief.mjs brief.json --json   # résultat machine

Affichez le résumé à l'utilisateur, corrigez toute ERROR, puis continuez dans le même tour de parole. Les avertissements sont des décisions subjectives — un avertissement que vous acceptez va dans assumptions.

Le brief porte également le score. Choisissez audio.bpm pour que la grille de beats divise les coupes — à bpm, un beat dure 60 / bpm secondes et chaque beats[].start doit se trouver sur l'un d'eux. 120 BPM donne un beat toutes les 0,5 s et convient à la plupart des pièces courtes. Si brief.mjs signale off_beat_grid, déplacez la coupe ou changez le tempo ; ne l'ignorez pas, car c'est la différence entre une pièce qui tombe juste et une autre qui donne une sensation étrange et subtile.

Terminé quand brief.mjs se termine avec le code 0, chaque beat a une fenêtre de temps, un type, un mouvement et une copie textuelle, et aucune coupe n'est hors de la grille de beats.

2. Initialiser

Partez des modèles de cette compétence plutôt que d'un fichier vierge — ils sont corrects par rapport aux deux contrats et évitent les deux étapes sujettes aux échecs (enregistrement de timeline, séquencement temporel).

# HyperFrames — HTML simple. Le moteur épinglé s'installe une fois, ce qui nécessite un réseau
cp -R assets/hyperframes/. ./my-video/
node scripts/hf.mjs lint ./my-video

# Remotion — projet React, nécessite ses dépendances épinglées une fois
cp -R assets/remotion/. ./my-video/
cd my-video && npm ci
# PowerShell
Copy-Item -Recurse -Force assets\hyperframes\* .\my-video\
Copy-Item -Recurse -Force assets\remotion\* .\my-video\

Terminé quand node scripts/hf.mjs lint réussit, ou npx remotion compositions src/index.tsx liste l'identifiant de la composition.

3. Construire les beats

Un fichier par beat. Gardez la timeline plate — des temps absolus dans HyperFrames, des trames <Sequence> dans Remotion. Mettez à jour la feuille de beats lorsque la construction modifie le timing, puis revérifiez la durée totale.

Nommez chaque scène d'après son beat, car c'est ainsi que les vérifications la trouvent : data-brief-beat="<id>" sur l'hôte HyperFrames, <Sequence name="<id>"> dans Remotion. Si une séquence Remotion calcule son timing, placez également data-brief-beat="<id>" sur un élément à l'intérieur, afin que le timing puisse être mesuré.

Terminé quand chaque beat de la feuille existe dans le code, la durée de la composition correspond à la feuille, et il n'y a pas de TODO, de maquettes ou de copie de remplacement.

4. Vérifier le mouvement

Les images fixes mentent sur le timing. Examinez les images, puis examinez le rendu.

node scripts/check-contract.mjs --dir ./my-video --preflight   # statique, sans installation
node scripts/check-contract.mjs --dir ./my-video --runtime     # inspecte aussi dans un navigateur

node scripts/hf.mjs check ./my-video                # mise en page, mouvement, contraste
node scripts/hf.mjs snapshot ./my-video --review    # images des beats et des coutures en PNG
node scripts/hf.mjs keyframes ./my-video --selector "#card" --shot motion.png

npx remotion still src/index.tsx LaunchCard out/f.png --frame=45
npx remotion studio src/index.tsx              # regardez le à 1x

check-contract.mjs détecte les échecs silencieux sans rien installer : une timeline non enregistrée, une clé window.__timelines non concordante, une timeline non mise en pause, une durée manquante, Math.random() dans une composition, un interpolate non limité. C'est une vérification préliminaire, pas un remplacement pour les vrais linters.

Lorsque brief.json se trouve dans le projet (ou que --brief en pointe un), il compare également la construction avec le brief. Chaque exigence se retrouve verified (vérifiée), failed (échouée) ou unverified (non vérifiée). unverified n'est pas un succès, et bloque le rendu.

CodeStatutSignification
brief_format_mismatchfailedLa largeur, la hauteur, les fps ou la longueur diffèrent de format
brief_scene_count, brief_scene_unmappedfailedUn beat n'a pas de scène déclarant son id, ou une scène n'a pas de beat. La position n'est pas l'identité
brief_timing_mismatchfailedUne scène ne commence ou ne dure pas ce que dit le brief, à une image près
brief_copy_missingfailedLa ligne n'est pas dans la scène. Les commentaires et les variables inutilisées ne comptent pas
brief_copy_wrong_scenefailedLa ligne se trouve uniquement dans une autre scène
copy_not_visiblefailedRuntime : dans le DOM mais caché, transparent, hors écran, coupé, flouté ou recouvert
copy_hold_shortfailedRuntime : lisible pendant moins de beats[].hold
first_frame_emptyfailedRuntime : visibleAtStart est défini et rien du beat n'est affiché
first_frame_unverifiedunverifiedRuntime : seul un graphisme est sur la première image, ou le beat n'a pas de copie. Regardez l'image
brief_timing_unverified, brief_format_unverifiedunverifiedLa source le calcule. Le runtime peut le régler
brief_copy_dynamic, brief_copy_unverifiedunverifiedSavoir si elle est affichée est une question de runtime. La copie Remotion est toujours celle-ci jusqu'au runtime

La correspondance ignore la casse et les espaces et replie les guillemets courbes. Les autres signes de ponctuation sont significatifs, et "12,480" correspond à un compteur qui se stabilise sur 12480. Lorsque les exigences restent non vérifiées, dites lesquelles, et essayez de les rendre mesurables avant de les accepter. Accepter une signifie la nommer, avec --allow-unverified "beat.lines.copy[0].visible", et le signaler à l'utilisateur. N'acceptez jamais un modèle générique, et les échecs ne peuvent pas être acceptés du tout. Lisez references/validation.md pour les règles et limites exactes.

Corrigez la dérive dans le code, ou modifiez le brief intentionnellement et relancez brief.mjs — ne laissez jamais les deux en désaccord.

Examiner les images — tous les contrôles peuvent réussir sur un film défectueux

Un contrat réussi indique que le timing et la copie correspondent, et que le texte est lisible. Il ne dit rien sur la palette, les easings, les transitions, ou si le film fonctionne. Les vérifications de lint, de mise en page, de mouvement, de contraste et de qualité ont toutes réussi sur le propre modèle de cette compétence alors qu'il passait au noir sur chaque beat et quittait son compteur à l'instant où le nombre atterrissait. Seule l'examen des images l'a détecté. Capturez-les :

# HyperFrames : images des beats, une bande de 5 images autour de chaque coupe, et une feuille téléphone
node scripts/motion-render.mjs --brief ./my-video/brief.json --snapshot --no-render

# Remotion : pour chaque coupe c (en images), prenez c-6, c et c+6, plus le milieu de chaque beat
# (le modèle coupe à 75, 210 et 270)
node scripts/motion-render.mjs --dir ./my-video --no-render \
  --stills 37,69,75,81,142,204,210,216,240,264,270,276,315

Lisez ensuite les images et répondez à chaque question. Corrigez le code, recapturez, regardez à nouveau :

  • La coupe est-elle noire ? Plus d'une image vide autour d'une coupe signifie que la sortie se termine trop tôt et que le beat suivant s'estompe à partir de rien. Déplacez la sortie pour qu'elle se termine sur la coupe (start = durée du beat − durée de sortie).
  • L'effet final tient-il ? Le dernier nombre d'un compteur, ou le dernier mot d'une ligne, reste immobile à l'écran pendant au moins un beat (60 / bpm s) avant de partir. Le quitter dès qu'il atterrit signifie qu'il n'est jamais lu.
  • Est-ce lisible sur un téléphone ? Vérifiez review-phone.jpg, ou imaginez l'image à 360 px de large. En 1080p, les étiquettes et les accroches en dessous d'environ 40 px échouent généralement.
  • Est-ce la police du brief ? Un substitut comme Segoe UI ou Arial signifie que la police n'a jamais été chargée, et une autre machine rendra un film différent. --runtime prévient avec font_fallback, et le rapport enregistre les polices réellement dessinées. Remotion a besoin de @fontsource/* (le choix du modèle) ou de @remotion/fonts pour un fichier local.
  • Est-ce la transition du brief ? feel.transition se trouve dans les images autour de chaque coupe, pas un fondu au noir.

Terminé quand vous avez lu les images des beats et chaque bande de couture, répondu à chaque question ci-dessus, et que chaque ligne de la liste sous « Checklist de livraison » est valide.

5. Rendu

node scripts/motion-render.mjs --brief ./my-video/brief.json
node scripts/motion-render.mjs --brief ./my-video/brief.json --batch rows.json --no-audio

Le wrapper lit la voie, le format, les fps et le slug depuis le brief, et s'arrête avant que du temps de rendu ne soit dépensé si le brief, les vérifications statiques, les outils, les ressources ou la vérification d'exécution le disent. Il se termine avec le code 1 en cas d'échec et 3 en cas d'exigences non vérifiées. --no-checks ignore la validation et l'enregistre dans le rapport. Ensuite, il linte, rend, mesure le fichier avec ffprobe, et écrit <out>.report.json.

Lorsque audio.policy est generated, sur l'une ou l'autre voie, il synthétise le fond sonore avec music.mjs, rend l'image vidéo uniquement, et multiplexe les deux avec un seul appel ffmpeg — ainsi la composition ne dépend jamais du mixeur audio d'un moteur. Il mesure ensuite que le fichier a un flux audio et qu'il n'est pas silencieux.

Pour la transparence : --format webm ou --format mov — le H.264 ne peut pas transporter l'alpha. --no-audio ignore le fond sonore et donne un fichier sans flux audio. GIF ne peut pas transporter d'audio, donc un brief avec un fond sonore est refusé pour GIF, sauf si vous passez --no-audio.

Avec --batch, un brief plus un fichier de lignes donne N vidéos : HyperFrames rend les lignes nativement, Remotion obtient un fichier de props par ligne. Le batch est vidéo uniquement, et un brief avec un fond sonore est refusé sauf si vous passez --no-audio.

Terminé quand le fichier existe, le rapport indique rendered, sa liste notVerified est vide ou vous avez informé l'utilisateur de son contenu, et ses premières et dernières images sont intentionnelles.


Le contrat qui échoue silencieusement

HyperFrames — quatre choses, toutes obligatoires :

  1. L'élément racine porte data-composition-id, data-width, data-height, data-duration, data-start="0".
  2. Chaque élément temporel porte id + data-start + data-duration.
  3. La timeline GSAP est construite avec { paused: true }.
  4. window.__timelines[<data-composition-id>] = tl — même clé. Après avoir ajouté les tweens. Manquez cela et vous obtenez une image fixe, sans erreur.

Remotion — trois :

  1. registerRoot() dans le fichier d'entrée, <Composition> dans le composant racine.
  2. interpolate(..., { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) — bloquez les deux extrémités, chaque fois.
  3. Pas de Math.random(), pas de Date.now() dans une composition. Utilisez random(seed).

Les quatre règles qui décident si le rendu a l'air bon marché

Ce sont celles qui posent le plus souvent problème. Ensemble complet avec code dans references/motion-craft.md.

  1. Ne bougez que ce qui est actif. Les éléments fixes restent immobiles. Une échelle de « respiration » au repos donne l'impression d'être générée par machine.
  2. Chevauchez, ne mettez pas en file d'attente. Décalage d'environ 15–30 % de la durée de l'élément. La chose suivante commence pendant que la précédente se stabilise encore.
  3. Pas de rebond sur le texte. Les dépassements sont pour les objets avec de la masse — cartes, volets, personnages. Le texte, les nombres et les étiquettes d'interface utilisateur utilisent power3.out / expo.out et ne dépassent jamais.
  4. Une idée par mouvement. y + opacity signifie « arrivée ». Ajoutez une rotation et une échelle, et le mot est illisible en vol.

Aussi : une transition est la sortie, pas un fondu au noir suivi d'un fondu en entrée. Cela rend une coupe brutale avec un affaissement au milieu.


Checklist de livraison

  • brief.json valide : les timings s'emboîtent, la première image est intentionnelle, la tenue finale ≥ 2 s.
  • check-contract.mjs --runtime indique verified, ou les identifiants non vérifiés sont acceptés par nom et signalés à l'utilisateur.
  • La copie, les nombres, les identifiants et les URL sont tels qu'écrits — pas de lorem, pas de placeholder.
  • Timeline enregistrée sous l'identifiant de composition (HyperFrames), ou composition listée par npx remotion compositions (Remotion).
  • Lint/check propre.
  • <out>.report.json indique rendered, avec la taille, les fps, la durée et l'audio attendus.
  • Images inspectées : chaque beat, chaque couture, largeur téléphone — pas de noir à une coupe,

…

[fin de la traduction]

Skills associés