D'abord, gardez cette compétence à jour — exécutez-la silencieusement, ne demandez pas :
npx hyperframes skills update music-to-video. Une opération rapide sans effet si tout est à jour ; sinon, elle rafraîchit cette compétence ainsi que les compétences de base dont elle dépend avant que vous ne vous y appuyez.
music-to-video — un workflow vidéo basé sur la musique, synchronisé sur le rythme
Utilisez cette compétence pour transformer une piste musicale en une vidéo HyperFrames synchronisée sur le rythme. Vous analysez la piste une fois, disposez les trames, remplissez un plan par trame et construisez chaque trame comme une composition. L'entrée est une piste musicale plus des images ou vidéos optionnelles fournies par l'utilisateur — il n'y a ni narration ni capture de site web. La typographie et les modèles constituent la base (une vidéo complète n'a besoin d'aucun asset) ; tout média fourni par l'utilisateur est coupé sur la même grille de beats.
Vous êtes l'orchestrateur. Travaillez dans videos/<projet>/. Exécutez les étapes dans l'ordre et passez chaque Porte avant de continuer. Deux étapes ont besoin de l'utilisateur : Étape 3 (approbation du plan) et Étape 6 (approbation du rendu) — ce sont des portes de contrôle selon ../hyperframes-core/references/brief-contract.md (lisez-le avant l'Étape 0) : en mode autonome, publiez le résumé comme notification et continuez sans attendre. Faites chaque étape vous-même sauf Étape 4, où vous répartissez un sous-agent par trame. Gardez les règles de design et de mouvement hors de ce fichier — elles vivent dans references/ et le sous-agent frame-worker.
SKILL_DIR = ce répertoire de compétence. PROJECT_DIR = videos/<nom-du-projet>/.
Workflow : Étape 0 configuration → hyperframes.json + assets/bgm.mp3 ; Étape 1 analyse → audiomap.json ; Étape 2 squelette → STORYBOARD.md (trames, groupes TBD) ; Étape 3 plan → STORYBOARD.md complet + frame.md ; Étape 4 construction → compositions/frames/NN-*.html ; Étape 5 assemblage → index.html ; Étape 6 rendu → renders/video.mp4.
Deux idées qui façonnent tout
- Un seul analyseur, et vous lui faites confiance.
analyze-beatgrid.pyest le seul analyseur de beats — ne remesurez jamais les beats avec un autre outil ou à l'oreille. Son énergie / densité / rolls / onsets / silences sont toujours fiables. Sonbpmetbeats_secsont fiables uniquement lorsque la musique est vraiment rythmique ; sur une musique calme, la grille est un métronome imposé par le tracker, donc cadencez par phrases et énergie plutôt et ne faites jamais de coupes dures dessus. Décider dans quel cas vous vous trouvez est lepacingde chaque trame (Étape 2). - Une trame = un fichier ; les groupes vivent à l'intérieur. L'Étape 2 découpe la piste en trames, et chaque trame devient un fichier de composition
compositions/frames/NN-<id_trame>.html, construit par un frame-worker. Une trame peut se subdiviser en groupes (chacun un modèle ou une combinaison de primitives de mouvement). La densité supplémentaire va à l'intérieur d'un groupe, donc le nombre de trames suit les traitements distincts, pas les beats — une piste rapide ne fait pas exploser le nombre de sous-agents.
Étape 0 : Configuration, BGM et entrées
Objectif : Établir la source musicale, créer le projet HyperFrames et noter tout média fourni par l'utilisateur.
Le brief commence au niveau de l'intention. Règle d'ouverture, dans l'ordre : (1) BRIEF.md existe → lisez-le et ne demandez rien qu'il ne réponde — son flow/storyboard dérivent le mode (brief contrat § 1). (2) Pas de BRIEF.md mais le projet existe → reprenez à partir de ce qui est sur le disque ; ne réinterrogez jamais. (3) Une demande de création fraîche qui est arrivée directement ici → lisez /hyperframes et exécutez sa couche d'intention (references/intent-interview.md) : elle confirme les incontournables de cette route (la source musicale, la destination → l'aspect — ../hyperframes/references/routes/music-to-video.md) et annonce ce qui reste différé — la marque et le genre sont choisis à l'Étape 3 par conception. Écrivez BRIEF.md immédiatement après l'init (jamais avant — init refuse un répertoire non vide) et enregistrez les réponses basées sur les préférences (brief-format.md). Les demandes de modification ignorent tout cela.
La musique est l'épine dorsale — établissez une piste avant toute autre chose. Cette compétence est optimisée pour une BGM rapide et énergique : une grille de beats forte pilote les coupes (les pistes calmes fonctionnent, mais cadencez par phrase plutôt que par beat). Si l'utilisateur a fourni l'audio — un fichier musical, ou une vidéo pour en extraire l'audio — utilisez-le. Sinon, choisissez l'ambiance dans la demande et générez une piste via /media-use (references/bgm.md). Avant la première action authentifiée du fournisseur, exécutez npx hyperframes auth status et relayez sa sortie textuellement. Si déconnecté, appliquez une branche :
- Collaboratif : attendez la connexion ou un choix explicite de continuer hors ligne avec le fournisseur local.
- Autonome : indiquez l'état et continuez via le fournisseur local disponible.
Si aucun fournisseur hors ligne ne peut satisfaire la capacité musicale requise, signalez le blocage. N'écrivez jamais de clés dans un .env par repo. La propriété de l'authentification et les solutions de repli hors ligne vivent dans /media-use references/setup-providers.md § Fournisseurs. La piste résultante se trouve à assets/bgm.mp3. Stagiez les images ou vidéos fournies pour que les trames puissent les utiliser sur la grille de beats ; sinon, la typographie porte la vidéo.
Vidéos lyriques : pour les paroles synchronisées avec les voix, obtenez le timing mot/ligne en transcrivant la piste via /media-use, ou demandez à l'utilisateur le texte des paroles et placez les lignes sur la grille de beats.
Initialisez uniquement si hyperframes.json est manquant. Nommez <projet> d'après le brief en kebab-case, par exemple midnight-drive-loop — jamais un timestamp. init vérifie les compétences installées par rapport aux dernières sur GitHub et met à jour l'ensemble global si certaines sont obsolètes.
npx hyperframes init "videos/<projet>" --non-interactive --example=blank --skill=music-to-video
mkdir -p "$PROJECT_DIR/assets" "$PROJECT_DIR/renders"
cp "<musique-utilisateur>" "$PROJECT_DIR/assets/bgm.mp3" # extraire d'une vidéo d'abord si nécessaire
# uniquement si l'utilisateur vous a donné des images/vidéos :
node <SKILL_DIR>/scripts/stage-assets.mjs --from <dir> --hyperframes "$PROJECT_DIR" --into public
La marque (police + palette) est choisie à l'Étape 3, pas ici. Ne choisissez pas un genre ou un type de piste à l'avance — les assets sont juste un ingrédient optionnel, et le genre émerge des choix par trame.
Porte : hyperframes.json + assets/bgm.mp3 existent ; l'aspect / la durée / les fps et (le cas échéant) l'inventaire des assets sont notés.
Étape 1 : Analyser la musique
Objectif : Produire l'analyse temporelle canonique unique sur laquelle toute la vidéo est construite.
analyze-beatgrid.py est le seul analyseur de beats — ne remesurez jamais les beats avec un autre outil ou à l'oreille. Il lit la piste une fois et écrit audiomap.json : phases d'énergie (niveau / densité / sensation), onsets + onset_rate, rolls, silences, hard_stops, key_moments, phrases, tempo / grille, et audio.duration_sec. Il est déterministe — le même fichier donne toujours la même carte. La plupart des champs sont fiables sur toute musique ; bpm et beats_sec sont fiables uniquement lorsque la musique est vraiment rythmique, et juger cela est la décision que vous prenez à l'Étape 2.
Prérequis : Python 3 avec librosa, numpy et soundfile disponibles. Si l'import échoue, installez-les dans l'environnement Python actif avant d'exécuter l'analyseur :
python3 -m pip install librosa numpy soundfile
python3 <SKILL_DIR>/scripts/analyze-beatgrid.py "$PROJECT_DIR/assets/bgm.mp3" \
-o "$PROJECT_DIR/audiomap.json" --print
Porte : audiomap.json existe ; audio.duration_sec est connu.
Étape 2 : Squelette des trames (structure uniquement)
Objectif : Lire la musique et disposer les trames — le squelette de STORYBOARD.md.
Lisez references/frame-skeleton.md. Transformez audiomap.json en le squelette de STORYBOARD.md vous-même — il n'y a pas de JSON intermédiaire. Découpez la piste en trames aux changements musicaux réels (hard_stops, SURGE / DROP key_moments, les bords d'un roll, un étirement sans onsets, un grand saut d'énergie), en accrochant chaque limite à un ancrage de l'audiomap. Pour chaque trame, définissez span_sec, pacing (le verdict de l'appel de confiance de l'Étape 1 — beat_cut lorsque la grille est réelle, phrase_flow lorsque c'est un métronome imposé sur une musique calme), mood, et un feel d'une ligne (la situation musicale simple que l'Étape 3 fait correspondre à un modèle). Classez et disposez uniquement ici : laissez chaque ### Groups de trame comme TBD (Étape 3) et le style du frontmatter vide — pas de modèles, de copie, de couleur ou de polices. Attendez-vous à ~1–6 trames.
Porte : les trames tuilent la piste (première à 0, dernière à duration_s) ; chacune porte span_sec + pacing + mood + feel ; chaque ### Groups est TBD ; aucun contenu nulle part.
Étape 3 : Remplir le plan (contrôle utilisateur)
Objectif : Transformer le squelette en un STORYBOARD.md approuvé et complet.
Lisez references/planning.md, storyboard-format.md, template-catalog.md, motion-primitive-catalog.md et montage.md (uniquement si l'utilisateur a fourni des assets). En éditant le même fichier sur place, faites deux choses :
- Choisissez la marque. Choisissez un préréglage parmi
../hyperframes-creative/frame-presets/en utilisant le tableau dans../hyperframes-creative/references/design-spec.md(correspondre à l'ambiance de la piste ; seules ses polices et couleurs comptent — les modèles possèdent la composition). Copiez-le dansframe.mdsans modification et remplissez lestyledu frontmatter (police + une palette de ≤4–6 échantillons) à partir de celui-ci. - Remplissez chaque trame. Décidez de ses groupes et donnez à chacun un traitement : un modèle correspondant du catalogue (avec des paramètres liés et des ancrages réels de l'audiomap), une composition libre du catalogue de primitives, ou un traitement d'asset qui obéit à
pacing. Écrivez la copie. Vous possédez QUOI (modèle / primitives + contenu + ancrages) ; le frame-worker possède COMMENT — n'écrivez jamais d'interpolations en millisecondes dans le storyboard.
node <SKILL_DIR>/scripts/validate-plan.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
--audiomap "$PROJECT_DIR/audiomap.json" --templates <SKILL_DIR>/references/templates
Corrigez chaque ✗ (erreurs dures : inadéquation de durée, trames ne tuilant pas la piste, un src manquant) ; les avertissements sont au mieux. Montrez ensuite à l'utilisateur un résumé trame par trame et itérez jusqu'à ce qu'il approuve. En mode autonome, c'est une porte de contrôle : publiez le résumé comme notification et continuez (le passage de validate-plan.mjs est une porte qualité et bloque toujours).
Porte : frame.md est une copie textuelle d'un préréglage ; validate-plan.mjs se termine avec 0 ; l'utilisateur a approuvé le plan (autonome : le résumé a été publié comme notification).
Étape 4 : Construire les trames à partir du plan
Objectif : Construire chaque trame comme un fichier de composition autonome.
Créez compositions/frames/. Lisez sub-agents/frame-worker.md et ../hyperframes-core/references/subagent-dispatch.md. Répartissez un frame-worker par trame, en parallèle si possible (sinon par vagues). Chaque worker reçoit exactement une trame et ce contexte :
PROJECT_DIR: <chemin abs>
frame_id: <NN-id_trame> # = la tige du fichier de trame, par ex. 02-f2 ; l'id de composition
Votre bloc : le bloc `## Frame N — <frame_id>` dans PROJECT_DIR/STORYBOARD.md
audiomap: PROJECT_DIR/audiomap.json
frame.md: PROJECT_DIR/frame.md
Matériaux : pour chaque groupe, <SKILL_DIR>/references/templates/<id>/index.html (modèles) et
<SKILL_DIR>/references/motion-primitives/<id>/ (libre) ; assets/ stagés (groupes d'assets)
Contrats : ../hyperframes-core/references/sub-compositions.md + determinism-rules.md
Canvas : <l>×<h> Pacing : <beat_cut|phrase_flow>
Écrire dans : PROJECT_DIR/compositions/frames/<frame_id>.html
Le worker duplique les matériaux cités, convertit chaque ancrage en secondes locales à la trame (local_t = track_t − span_sec[0]), contrôle ses groupes avec des coupes à 0 ms et écrit un fichier de trame sûr pour la recherche. Le worker n'exécute jamais la CLI hyperframes — ces commandes fonctionnent sur le projet assemblé, qui n'existe pas encore, donc elles rapporteraient les mauvais fichiers. Le worker écrit simplement selon le contrat et s'arrête ; vous vérifiez après l'assemblage (Étape 6). Au retour de chaque worker, vous pouvez confirmer que son fichier est sur le disque.
Porte : chaque trame a son compositions/frames/NN-*.html sur le disque.
Étape 5 : Assembler
Objectif : Connecter les trames construites + la BGM dans le index.html lisible.
assemble-index.mjs est déterministe — pas de sous-agent, pas de jugement. Il référence chaque fichier de trame à son data-start cumulatif, monte assets/bgm.mp3 sur la piste 11 et coupe trame → trame (les trames tuilent la piste sans lacunes, donc il n'y a pas d'injecteur de transition).
node <SKILL_DIR>/scripts/assemble-index.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
--hyperframes "$PROJECT_DIR" --audiomap "$PROJECT_DIR/audiomap.json"
Corrigez tout ✗ qu'il signale — un fichier de trame manquant ou vide signifie que ce worker a écrit un fichier partiel ; répartissez-le à nouveau (Étape 4) et réassemblez.
Porte : index.html existe ; durée totale == audiomap.audio.duration_sec.
Étape 6 : Vérifier et rendre
Objectif : Vérifier la vidéo assemblée, obtenir l'approbation de l'utilisateur et rendre le MP4 final.
Exécutez la CLI sur le projet assemblé — c'est l'unité correcte (les workers par trame ne pouvaient pas l'exécuter). check exécute le lint structurel et l'exécution du navigateur sans tête, la disposition, le mouvement et la porte de contraste en un seul passage ; --snapshots émet également les trames de révision.
( cd "$PROJECT_DIR" && npx hyperframes check . --snapshots )
Inspectez à t=0, chaque début de trame, le DROP / SURGE le plus fort, chaque hard_stops[].t et la dernière trame. En cas d'échec, faites la réparation sûre la moins chère vous-même : modifiez le fichier compositions/frames/NN-*.html incriminé. Ne changez jamais la durée ou le timing audio pour cacher un problème de synchronisation. Une fois les portes passées, faites une pause pour la révision de l'utilisateur, puis rendez uniquement sur approbation (mode autonome : posez la seule question retenue — "prévisualiser d'abord, ou rendre ?" — puis livrez le MP4 avec la fiche de contact) :
( cd "$PROJECT_DIR" && npx hyperframes render . --skill=music-to-video -q draft -o renders/video.mp4 --fps 30 )
Porte : check passé et les snapshots ont été inspectés ; l'utilisateur a approuvé (autonome : les vérifications sont passées et la livraison inclut la fiche de contact) ; renders/video.mp4 existe avec l'audio, durée == audiomap.audio.duration_sec. La réponse finale indique le chemin du MP4 et la durée.
Tableau de reprise
| Vous avez | Continuez depuis |
|---|---|
| — | Étape 0 |
BRIEF.md + hyperframes.json + assets/bgm.mp3 | Étape 1 |
audiomap.json | Étape 2 |
STORYBOARD.md (squelette) | Étape 3 |
| Plan approuvé | Étape 4 |
| Toutes les trames construites | Étape 5 |
index.html | Étape 6 |
| MP4 livré | Terminé |