Vidéo musicale (motion design)
Vous ne pouvez pas entendre la chanson. Tout le visuel est indexé sur des données mesurées, donc la première tâche est toujours le dossier de la chanson. Si les données de la chanson sont erronées, chaque image est erronée.
Les assistants se trouvent à côté de ce fichier. Exécutez-les avec le dossier de compétence run.py (le chemin d'installation par défaut est indiqué ; ajustez si vous avez installé ailleurs) :
python3 ~/.claude/skills/music-video/run.py song-folder SONG.mp3 OUT_DIR [--fps 30] [--lyrics-lang en|tr] [--lyrics-text known.txt]
python3 ~/.claude/skills/music-video/run.py analyze SONG.mp3 # beats/bars/sections as JSON
python3 ~/.claude/skills/music-video/run.py dance2d SONG.mp3 --out DIR --analysis OUT_DIR/song-map.json --start 23.8 --dur 14.3 [--render]
Ne prétendez jamais avoir écouté la chanson. Dites « d'après l'analyse ».
1. Dossier de la chanson (toujours en premier)
| Fichier | Contenu | Outil |
|---|---|---|
| passage. | l'audio, copie octet par octet (vérification sha256) ; utilisez-le tel quel dans le montage final | — |
| song-map.json / .md | bpm, temps, downbeats/mesures, sections d'énergie (calme/construction/forte), énergie par temps, chutes | Beat This! → aubio CLI → tracker numpy intégré |
| stems/ | voix / batterie / basse / autre (mis en cache, les réexécutions sont rapides) | demucs htdemucs (optionnel) |
| envelopes.json | volume par image du mix et de chaque piste (dB + 0..1) | numpy |
| hits.json | attaques de kick / caisse claire / hi-hat avec force 0..1 | flux spectral par bande sur la piste de batterie |
| notes.json | notes de mélodie et de basse (optionnel) | basic-pitch |
| lyrics-passage.json / .md | lignes avec temps des mots | whisper.cpp whisper-cli sur la piste vocale |
| song-story.md | MODÈLE que vous remplissez : thème, voix, arc émotionnel, image clé par section | vous, d'après les paroles + la carte |
| README.md | ce qu'est chaque fichier, unités (secondes), fps | généré |
Règles :
- Les sections sont des phrases d'énergie (phrases de deux mesures classées par l'énergie propre de la chanson), pas couplet/refrain. Nommez-les vous-même dans song-story.md.
--lyrics-textavec les vraies paroles (une ligne par ligne) les aligne sur les mots de whisper ; les mots qui n'ont pas pu être appariés reçoivent des temps interpolés (matched: false). Sans cela, les lignes sont la sortie brute de whisper : vérifiez-les. Les lignes sur une piste vocale silencieuse sont marquéessuspect(whisper hallucine sur les instrumentales). Les chansons instrumentales ignorent whisper.- Chaque étape lourde dégrade au lieu d'échouer : pas de Beat This! → aubio (CLI externe) → tracker numpy (pas de downbeats réels, 4/4 supposé) ; pas de demucs → enveloppes et attaques du mix uniquement ; pas de basic-pitch → pas de notes.json ; pas de whisper → pas de paroles. Les
warningsde l'exécution indiquent ce qui a été sauté. Informez l'utilisateur. - hits.json est suffisant pour les flashs, secousses et pops d'échelle, pas une transcription de batterie : les hi-hats se déclenchent aussi sur les caisses claires, les notes de basse peuvent fuir dans la bande de la caisse claire.
- song-story.md n'est jamais écrasé lors des réexécutions. Écrivez uniquement ce que les paroles et l'analyse soutiennent ; laissez un titre comme « inconnu » plutôt que d'inventer un sens.
2. Plan créatif (montrez-le avant le rendu)
- Un concept qui vient de song-story.md, un monde, une palette, une police libre (OFL) pour la typographie des paroles.
- Tableau Section → scène : un changement de section = un changement de scène ou de caméra ; le refrain / la section de plus haute énergie obtient l'idée visuelle la plus grande, répétée avec variation à chaque fois ; les chutes = coupe, flash ou échelle sur le downbeat.
- Typographie des paroles uniquement sur les lignes clés (mots cinétiques sur leurs temps de mot), pas de karaoké pour chaque ligne.
- En musique calme, rythmez par phrase et énergie ; ne coupez pas sec sur chaque temps suivi. Le nombre de traitements distincts importe plus que le nombre de coupes.
- Montrez le plan (tableau + 3–4 images décrites ou rendues) et obtenez une approbation avant le rendu complet.
- Blocs de construction à lire en premier : la compétence
music-to-videod'HyperFrames (github.com/heygen-com/hyperframes,skills/music-to-video/, Apache-2.0) dispose d'un catalogue de primitives de mouvement de coupe au rythme (flash cut, crash zoom, whip, split chromatique, secousse d'écran, lettres cinétiques…) et de mises en page de paroles.
3. La vidéo de danse 2D intégrée
Regard : personnages plats (tête sombre ronde, membres en traits arrondis, chemise et chaussures colorées), portes arquées en miroir, fonds tournants en forme de soleil dans les tons violet / sarcelle / or / rose, mots de paroles en police condensée grasse (Anton) avec un mot d'accent, une rangée de doubles miroirs du danseur en différentes couleurs, bande de film, couronne et accessoires d'échecs. Inspiré par la vidéo 2D « low effort » de l'expérience YouTube de Devarf avec un clip vidéo réalisé à chaque niveau d'effort.
Planificateur (musicvideo/dance2d.py, pur et ensemencé) :
- la fenêtre s'accroche aux downbeats ; une pose clé par temps, la pose ARRIVE sur le temps ;
- les downbeats obtiennent une grande pose (construction : brasEnL'Air / pointer / taper, fort : sauter / brasEnL'Air) et un fléchissement complet des genoux ;
- le jeu de mouvements (une phrase de 4 temps) change à chaque mesure selon le niveau d'énergie et ne se répète jamais deux fois de suite ;
- les scènes coupent au début des sections et toutes les 4 mesures (changement de palette, vitesse du fond rotatif selon le niveau, direction alternée ; portes en sections calmes/construction, échecs + rangée de 5 danseurs en sections fortes, couronne sur le leader) ;
- doubles du danseur : calme 1, construction 3, fort 5 ;
- JSON des paroles
[{start, end, text, accent}]en secondes de la fenêtre → chaque mot atterrit sur un temps.
Armature (runtime/char2d.js, window.Char2D) : groupes SVG avec pivots (hanches > jambes > tibias > chaussures, torse > bras > avant-bras, tête). Les angles des membres sont en degrés positifs vers l'extérieur (0 vers le bas, 90 sur le côté, 180 vers le haut) de sorte qu'une pose fonctionne des deux côtés ; un verrouillage au sol maintient le pied inférieur au sol (les squats descendent d'eux-mêmes), air lève pour les sauts. Poses : idle, stepG/D, armsUp, swayG/D, pointG/D, clap, jump, squat, handsOnHips (mirror(p) échange les côtés). poseAt(keys, t) maintient, puis atténue la dernière ≤0,26 s avec dépassement sur les grands coups. runtime/dance2d.js dessine le plan à partir de window.MV_DANCE ; une animation GSAP pilote un setter proxy → draw(t), donc chaque image est une fonction pure de t.
Sortie de dance2d : DIR/plan.json et DIR/project/ (un projet HyperFrames). Avec --render également DIR/dance2d.mp4 : 1920×1080, 30 ips, H.264 yuv420p, l'audio propre de la chanson pour la fenêtre (AAC, sans fondu). La musique sous CC BY nécessite le --credit à l'écran.
Le rendu est le choix de l'utilisateur. --render exécute npx hyperframes render, qui télécharge et pilote un Chrome/Chromium sans tête. Demandez avant de l'utiliser. Sans cela, tout jusqu'au dossier du projet fonctionne avec Python seul. GSAP n'est pas fourni : placez gsap.min.js dans runtime/ (ou définissez MV_GSAP), sinon le projet charge GSAP 3.14.2 depuis le CDN jsDelivr au moment du rendu.
4. Personnages au-delà de l'armature intégrée (apportez les vôtres)
Cette compétence ne fournit aucun modèle 3D. Si l'utilisateur souhaite des personnages 3D (Three.js) :
- utilisez des modèles dont la licence autorise la redistribution dans une vidéo finale, par exemple des modèles CC0, ou des personnages et animations que l'utilisateur télécharge depuis son propre compte Mixamo (c'est acceptable dans une vidéo finale ; les fichiers bruts ne doivent pas être redistribués ou commités dans un dépôt public) ;
- ne copiez jamais de modèles d'exemple d'autres projets sans vérifier leur licence ;
- ou restez sur des primitives procédurales (capsules, sphères, boîtes sur une simple chaîne d'os), qui n'ont aucun problème de licence.
La déterministe par image s'applique toujours :
mixer.setTime(t * rate)chaque image, jamaismixer.update(dt);rate = song_bpm / clip_bpm; changez de clip aux limites de mesure.
5. Règles de rendu (tout moteur de rendu)
- Tout est une fonction pure de
t = frame / fps. Pas deDate, pas de deltasrequestAnimationFrame, pas deMath.random()sans graine. - Petits coups (secousse de caméra, flash lumineux, pop d'échelle) sur kick/caisse claire depuis hits.json ; luminosité ou lueur depuis envelopes.json.
- Sortie : 1920×1080 (ou 1080×1920 pour Reels/Shorts), 30 ips, H.264 yuv420p, AAC, même durée que la chanson (ou la fenêtre choisie).
- Photosensibilité : jamais plus de 3 flashs plein écran par seconde.
- Budget : plus de temps de réflexion donne un meilleur mouvement, mais révisez en une session. Les boucles de révision multi-agents sur un seul clip vidéo brûlent rapidement des tokens et ont tendance à redémarrer après les limites.
6. Vérifications avant livraison
- Joue jusqu'à la fin ; durée == durée de la chanson (ou de la fenêtre) ±1 image.
- Le flux audio est la chanson originale (comparez le hachage PCM décodé, ou un pic de corrélation croisée au décalage 0).
- Vérification ponctuelle de synchronisation : rendez 5 images sur les downbeats du refrain et confirmez que la pose de coup / flash atterrit là.
- Une planche contact par section (
ffmpeg -i out.mp4 -vf "fps=1,scale=480:-1,tile=4x4" sheet.jpg) et regardez-la effectivement. report.md: ce que vous avez fait et pourquoi, comment, ce que vous avez vérifié, ce dont vous n'êtes pas sûr.