Changelog → Vidéo de marque
Entrée : un fichier changelog .md (thèmes + éléments, comme le digest hebdomadaire HyperFrames).
Sortie : un projet HyperFrames propre, vert « seam-gate », dans le dossier projects/active/weekly-changelog-<plage>/. Ne rend que sur demande.
À charger impérativement en premier : motion-doctrine (+ cut-the-curve, oversized-cursor si un curseur apparaît, seam-craft) et captions-overlay. Ce skill fournit le pipeline spécifique au changelog ; la doctrine fournit la loi du mouvement.
La directive primordiale : visualiser, ne pas lister
Chaque thème est illustré par une maquette animée de l'UI réelle ou d'un analogue fidèle qui exécute le changement dans l'expérience — jamais de puces de texte. Acheminez chaque thème/élément via references/visualization-registry.md AVANT d'écrire le script ; le registre décide ui-recreate / ui-analog / terminal / checklist. La checklist textuelle est le DERNIER recours, réservée aux éléments véritablement non visuels (listes de correctifs de fiabilité).
Pipeline
0 · Amorcer le projet à partir des assets de CE skill — non négociable
Faites ceci AVANT d'écrire du HTML de composition. Sauter cette étape produit toujours une vidéo qui ressemble à un projet similaire que vous avez construit avant, PAS à la marque de ce skill — c'est la façon la plus courante que ce skill dévie de la marque. Les assets, polices et échafaudage du skill sont le skill ; le prompt SKILL.md est un routeur.
mkdir -p project/assets/fonts
cp <SKILL_DIR>/assets/fonts/*.woff2 project/assets/fonts/
cp <SKILL_DIR>/assets/bgm.mp3 project/bgm.mp3
ffmpeg -y -stream_loop 15 -i <SKILL_DIR>/assets/bg-pattern.mp4 -t <TOTAL> \
-vf "scale=1080:1080,fps=30,eq=saturation=0.72,[email protected]:t=fill" \
-an -c:v libx264 -crf 20 -pix_fmt yuv420p project/assets/bg-pattern-<TOTAL>s.mp4
cp <SKILL_DIR>/examples/master-skeleton.html project/index.html
Ensuite, lisez references/build-spec.md de bout en bout (pas en diagonale) — il définit les tokens de marque (TT Norms Pro + ABC Solar Display + TT Norms Mono, crème #f5f6f4, vert rationné #5ef17c, cartes vitrées avec bordures teintées vert, forme de pilule pour kicker/sec-chip, rail de sous-titres de 32px à top: 990) que chaque scène hérite de l'échafaudage.
Seulement ALORS, commencez les étapes 1 à 6 ci-dessous. Les étapes 1-4 (analyse, routage, script, VO) planifient ce qui va dans l'échafaudage ; l'étape 5 remplit les espaces réservés (<RANGE>, <TOTAL>, <CUT_N>, <DUR_N>, corps de scène) à l'intérieur du project/index.html déjà copié — vous ne réécrivez PAS le chrome, les polices, la palette ou la coque de mise en page de l'échafaudage.
Si vous vous surprenez à chercher cp sur un index.html de vidéo précédente, ou à écrire vos propres déclarations @font-face, ou à concevoir un fond de shader WebGL au lieu d'utiliser le MP4 bg-pattern encodé ci-dessus : ARRÊTEZ. Supprimez le index.html actuel et recommencez au cp de l'échafaudage maître. Reconstruire le contenu de la scène sur le bon échafaudage est moins coûteux que de rétrofit la marque dans le mauvais échafaudage.
1 · Analyse + coupe éditoriale
- Extraire : plage de semaine, statistiques principales (versions, commits), thèmes, éléments.
- Budget : 45-60s total. Titre ≤2s, outro ≤3.5s, 4 thèmes ≈ 9-12s chacun.
- Par thème, garder UNE visualisation héroïque + au maximum 3 éléments parlés. Tout le reste n'existe que comme pointeur vers le « digest complet » dans l'outro. Couper est le travail : un changelog avec 30 éléments donne quand même ≤14 temps parlés.
- Ordonner les thèmes par histoire : fonctionnalité phare → surface produit → performance → fiabilité (le digest suit généralement déjà cet ordre).
2 · Routage de visualisation
Pour chaque thème, choisir la surface depuis references/visualization-registry.md et écrire une ligne : thème → surface → les 2 à 4 actions séquencées que la maquette effectue, chacune liée à une phrase du script. Si aucune surface du registre ne correspond et qu'aucun analogue fidèle n'existe, c'est une scène de checklist — n'inventez pas d'UI factice pour quelque chose que nous ne pouvons pas représenter honnêtement.
3 · Script à deux couches (parlé vs affiché)
Écrire le script sous forme de lignes de jetons selon references/script-voice.md : registre conversationnel, chaque terme technique portant une forme phonétique spoken de references/lexicon.json tandis que display conserve l'orthographe standard. Les sous-titres montrent display ; la VO lit spoken. Tout terme absent du lexique : ARRÊTEZ et demandez à l'utilisateur comment il se prononce, puis ajoutez-le au lexique.
Enregistrer sous script-tokens.json dans le projet.
4 · VO — Annie (HeyGen, épinglée)
# texte de la couche parlée uniquement ; words JSON = horodatages de vérité terrain du texte PARLÉ
# Chemin natif du dépôt : le skill changelog-video s'exécute depuis la racine du dépôt hyperframes,
# donc il utilise directement l'assistant TTS tracké hyperframes-media (pas d'étape d'installation
# `npx hyperframes skills`). Si vous avez copié le skill dans un autre dépôt, échangez
# votre propre chemin vers le media-use / hyperframes-media heygen-tts.mjs.
node skills/hyperframes-media/scripts/heygen-tts.mjs ./vo-spoken.txt \
-o voiceover.mp3 --words vo-words.json \
--voice 330290724a1b470fb63153f34d4c0183 # Annie — réaliste (ne pas substituer)
Nécessite le CLI heygen ≥0.3.0 authentifié (heygen auth login --oauth).
Ensuite aligner les horodatages parlés sur les jetons d'affichage :
node <SKILL_DIR>/scripts/align-captions.mjs \
--tokens script-tokens.json --words vo-words.json --out captions.json
captions.json est l'entrée du rail de sous-titres (orthographe d'affichage, timing parlé). L'aligneur imprime des avertissements MISMATCH — résolvez chacun d'eux avant de construire (généralement une orthographe de lexique que le TTS rend en plusieurs mots). L'audio est l'horloge : tous les temps de battement viennent de vo-words.json ; une régénération de VO rouvre chaque couture.
Les horodatages par mot sont une barrière stricte. Avant de passer à l'étape 5, vérifiez que vo-words.json n'est pas vide et possède un tableau words: [...] avec start/end par mot. S'il est vide (0 octet) ou manque le tableau — un mode de défaillance connu lorsque le fournisseur TTS renvoie l'audio mais pas la charge utile d'horodatage — NE CONTINUEZ PAS sans eux. Solution de secours : aligner de force l'audio produit contre le script d'affichage en utilisant whisper local :
uvx --from openai-whisper whisper voiceover.mp3 \
--model base.en --language en --word_timestamps True \
--output_format json --output_dir .
# puis exécutez align-captions.mjs avec --words voiceover.json (même forme)
Whisper interprète mal les rendus TTS ("gee-sap" → "gsap", "heyjen" → "hey Jen", etc.) — les sous-titres utilisent toujours l'orthographe DISPLAY de script-tokens.json ; whisper ne fournit que les horodatages. align-captions.mjs gère la jointure. Cette solution de secours fait la différence entre une version sous-titrée et une version silencieusement non sous-titrée.
5 · Construction
Suivez references/build-spec.md exactement : tokens de marque + polices (regroupées dans <SKILL_DIR>/assets/), l'encodage du fond animé, l'échafaudage de scène, le chrome, le rail de sous-titres, un moment vert rationné par scène. Ensuite l'ordre de la doctrine : ledger.json (toutes les coutures ordinaires cut-the-curve GAUCHE) → seam-stamp → battements internes sur les mots de VO → vérification seam-gate.
Les sous-titres ne sont pas optionnels. L'échafaudage maître embarque une IIFE de rail de sous-titres qui lit un tableau LINES — laisser ce tableau vide est un bug livré, pas un choix de style. Peuplez-le à partir de captions.json avant de passer à l'étape 6 :
// coller à la place de "const LINES = /* … */ []" dans l'IIFE du rail de sous-titres :
const LINES = /* contenu de captions.json */ [
{ id: 0, end: 2.74, w: [["This", 0.0], ["week,", 0.30], …] },
…
];
Si align-captions.mjs a été sauté ou que LINES est [], la vérification de trame à l'étape 6 échouera — ne la masquez pas en supprimant #cap-line de l'échafaudage.
6 · Vérifications (toutes vertes avant présentation)
node packages/cli/bin/hyperframes.mjs check --caption-zone "x0=0;y0=.90;x1=1;y1=1;severity=error;seek=.02,.06,.10,.14,.18,.22,.26,.30,.34,.38,.42,.46,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98"(ou le CLIhyperframesinstallé depuis le skill localskills/hyperframes-cli/) — 0 erreurs (contraste : texte atténué ≥ .66 alpha ; le contenu de la scène reste au-dessus du rail de sous-titres). N'utilisez PASnpx hyperframes@latest; le CLI local tracké est la source de vérité pour le contrat de composition que ce skill produit.seam-gate.mjs verify— 0 échec.- Redémarrez le serveur de prévisualisation (il met en cache le bundle), vérifiez 3-4 temps via
__player.seeksur la page de composition brute. - NE RENDEZ PAS sauf si l'utilisateur le demande. Après un rendu demandé, vérifiez les trames du MP4 (
ffmpeg -ss <t> … -frames:v 1) : sous-titres présents, vidéo de fond non noire, pas de trames minuscules/figées. - Vérification de présence des sous-titres — échec strict. Échantillonnez 3-4 trames réparties sur la fenêtre parlée de la VO (par ex.
t=3,t=15,t=30,t=42pour une VO de 48s) et confirmez que le rail de sous-titres àtop: 990affiche du texte visible sur chacune. Si une trame dans un intervalle parlé manque de sous-titres, la version est livrée sans sous-titres — traitez-la comme une vérification rouge et revérifiez le remplissage deLINESà l'étape 5. C'est exactement ce qui a mal tourné sur la version du 13-20 juillet v4.
Structure du projet
projects/active/weekly-changelog-<plage>/
├── index.html # document maître unique (scènes comme diapositives, coutures estampillées)
├── ledger.json # registre vectoriel (entrée seam-stamp)
├── script-tokens.json # script à deux couches (source de vérité pour VO + sous-titres)
├── vo-spoken.txt # généré : couche parlée, une ligne
├── voiceover.mp3 + vo-words.json + captions.json
├── bgm.mp3 # copie depuis <SKILL_DIR>/assets/bgm.mp3 (la piste maison) sauf si l'utilisateur en fournit une
└── assets/fonts/ + assets/bg-pattern-<dur>s.mp4
Anti-patrons
| À ne pas faire | À faire à la place |
|---|---|
| Diapositives à puces pour les changements UI | Maquetter la surface en train d'exécuter le changement |
| UI factice pour des éléments non représentables | Scène de checklist honnête |
| Texte "JSON"/"CLI" brut dans le texte TTS | Formes parlées du lexique ; l'affichage reste standard |
| Orthographes phonétiques dans les sous-titres | Les sous-titres affichent toujours la couche d'affichage |
| Deviner la prononciation d'un terme inconnu | Demander, puis enrichir le lexique |
| Parler de chaque élément du changelog | ≤3 par thème ; le lien du digest porte le reste |
| Accents verts partout | Un moment vert par scène (#5ef17c) |
| Partir du index.html d'une vidéo précédente | Étape 0 — copier examples/master-skeleton.html de ce skill dans project/index.html, toujours |
@font-face / shader WebGL / BGM personnalisé | Étape 0 — copier les assets/ de ce skill textuellement ; les assets du skill SONT la marque |
| Livré sans invalidation CloudFront | Exécuter aws cloudfront create-invalidation sur la distribution E2BSLVSZ7FG3U0 pour le chemin exact après tout remplacement S3 — le CDN met en cache l'ancien fichier sinon |
Livrer avec le tableau LINES vide dans l'échafaudage | L'étape 4 doit produire un captions.json rempli ; l'étape 5 doit le coller dans l'IIFE ; l'étape 6 vérification 5 doit confirmer les sous-titres sur les trames rendues. Un LINES vide = livraison non sous-titrée = refaire l'exécution |
Pas de vo-words.json → sauter les sous-titres et livrer quand même | Revenir à l'alignement forcé whisper sur l'audio produit ; les sous-titres ne sont pas optionnels |