Communitygithub.com

hongliangzheng11/lyric-video-skill

Génère des vidéos de paroles bilingues verticales 1080×1920 avec HyperFrames : fond sombre et onirique, un seul objet géométrique en verre transparent qui se déforme en rebondissant, un petit groupe d'animaux en bas et les paroles originales + chinoises au centre, synchronisées à partir des timings réels de Whisper.

Qu'est-ce que lyric-video-skill ?

Ce skill définit une pipeline de production complète et immuable pour créer des vidéos de paroles bilingues (original + chinois) au format vertical 1080×1920, destiné aux chansons audio (MP3/WAV). L'utilisateur fournit uniquement le fichier audio et le nom de l'artiste ; le skill gère tout le reste : transcription (via faster-whisper ou un modèle multilingue pour les chansons multilingues), alignement des paroles, génération de l'animation et rendu final via HyperFrames. Il offre deux chemins : 3A (paroles officielles fournies, utilisées comme texte exact avec des timings recalibrés par réanalyse) et 3B (paroles reconstruites à partir de Whisper). Le style visuel est fixe : fond sombre avec des taches lumineuses, un unique objet en verre transparent qui se déforme aux bords, un groupe d'animaux en boucle en bas, et les paroles centrées (police Inter pour l'original, SimSun pour le chinois en couleur chaude). Le skill inclut des scripts pour la création de projet, la transcription, l'alignement précis des paroles (avec vérifications strictes), le mouvement aléatoire déterministe, et la vérification de la qualité (résolution, fps, durée, captures d'écran). Il fonctionne sur Windows avec HyperFrames et Python, et possède des règles strictes : pas de synchronisation basée sur le BPM, priorité aux paroles officielles, pas de modification non autorisée des spécifications, et vérification manuelle obligatoire des screenshots et de la planche contact.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add hongliangzheng11/lyric-video-skill

Demander à votre IA préférée

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

Documentation

Pipeline standard de vidéo de paroles

Une pipeline de style fixe et déjà validée. L'utilisateur n'a qu'à fournir le fichier audio et le nom de l'artiste ; le reste est exécuté selon cette norme sans reconception visuelle. Les paroles officielles sont optionnelles : si fournies, empruntez le chemin rapide 3A (texte zéro devinette), sinon empruntez le chemin de reconstruction 3B ; dans les deux cas, les timings doivent être réels.

Entrée / Sortie

EntréeDescription
AudioObligatoire. N'importe quel MP3/WAV/FLAC, durée illimitée
Nom de l'artisteObligatoire. Utilisé pour l'en-tête, le logo permanent et le générique de fin
Paroles officielles (optionnel)Priorité si l'utilisateur les fournit : texte zéro devinette, les timings sont entièrement recalibrés par réanalyse réelle (voir 3A). Sinon, reconstruction avec Whisper (3B)
Titre de la chanson (optionnel)Par défaut, prend le nom du fichier ; Artist - Title.mp3 supprime automatiquement le préfixe de l'artiste
Phrase d'accroche (optionnel)Une ligne en chinois sous le titre de l'en-tête, par défaut non affichée

Sortie : <project>/renders/video.mp4 + renders/contact-sheet.jpg + transcript.json + NOTES.md.

Spécifications fixes (non modifiables sans autorisation)

  • Vertical 1080 × 1920, 30 ips, durée totale égale à la durée réelle de l'audio (pas de recadrage, pas d'étirement, pas de changement de vitesse).
  • Audio : fichier original, le gain est uniformisé par le framework lors du rendu (data-volume="0.9").
  • Fond : noir pur à bleu-violet très foncé, deux groupes de taches lumineuses décalées en fondu croisé lent ; aucun filtre CSS plein écran (cela laisserait des jointures de blocs).
  • Sujet principal : un seul objet en verre transparent, 8 formes géométriques arrondies (sphère/ellipse horizontale/ellipse verticale/rectangle arrondi/ losange/triangle/pentagone/hexagone), qui se comprime de 11% le long de la normale lorsqu'il touche le bord de l'écran → se transforme en une autre forme en 0,94 s → rebondit et continue à dériver. Une seule timeline pour toute la chanson, pas de réinitialisation lors du changement de paroles.
  • Bas : petit groupe d'animaux (chat/ours/pingouin/renard) en boucle de 4,5417 s, collé en bas 1080×526, calque au-dessus des taches lumineuses du fond et en dessous de l'objet en verre, mix-blend-mode: screen.
  • Sous-titres : bloc entier centré optiquement sur le centre vertical de l'écran (y≈960) ; anglais/original en haut (Inter, taille de police adaptative à la largeur de la ligne), chinois en bas (SimSun, couleur brune chaude #DDA97D), fondu entrée/sortie par groupe.
  • Crédits : utilisez uniformément le nom de l'artiste, n'apparaissez aucun mot-clé de section comme VERSE / CHORUS / BRIDGE à l'écran.

Les paramètres de détail, couleurs, tailles de police et pièges se trouvent dans references/style-spec.md.

Procédure

Soit HF = racine d'installation d'HyperFrames (par défaut G:\hyperframes), PY = Python avec faster-whisper (par défaut C:\Users\Admin\.workbuddy-ai\binaries\python\envs\hf\Scripts\python.exe), SK = répertoire de ce skill.

1. Créer le projet

"$PY" "$SK/scripts/new_project.py" "<chemin_audio>" "<nom_artiste>" [--title "titre_chanson"] [--tagline "une_ligne_chinois"] [--root G:/hyperframes/videos]

Notez absolument le chemin absolu du projet. Cela : crée un répertoire unique → copie l'audio → convertit en WAV 16 kHz mono → exécute analyze-beatgrid.py officiel pour générer audiomap.json → copie la feuille de sprite des animaux et GSAP → écrit project.json.

Ne jamais écraser un répertoire de projet existant ; pour modifier une œuvre livrée, créez un nouveau projet.

2. Transcrire

"$PY" "$SK/scripts/transcribe.py" "<project>" --model medium.en --lang en

Pour une chanson de 3-4 minutes sur CPU int8, cela prend environ 3-6 minutes. Pour les chansons non anglaises, remplacez --lang par la langue correspondante et retirez .en de --model. Produit whisper_raw.json (timings au niveau des segments et des mots).

Pour les chansons multilingues (anglais+japonais, anglais+coréen, etc.) n'utilisez pas transcribe.py : --lang verrouille une seule langue, l'autre sera transcrite de force dans la première — le résultat sera lisible mais complètement faux, plus dangereux que pas de transcription du tout. Utilisez plutôt la détection automatique de langue par fenêtre :

"$PY" "$SK/scripts/transcribe_mixed.py" "<project>" --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo"

Il décode par fenêtres de 14 s avec pas de 10 s, chaque fenêtre détermine sa propre langue, ne conserve que les mots centraux de la fenêtre (les zones de chevauchement sont supprimées, pas de duplication), imprime une carte des langues et écrit whisper_mixed.json. Consultez d'abord la carte des langues : les endroits où la langue change sont généralement les limites de sections. Notez que les modèles .en (medium.en / small.en) sont des modèles purement anglais, physiquement incapables de produire du japonais ; les chansons multilingues doivent impérativement utiliser un modèle multilingue.

Pour le chemin 3A (paroles officielles) cette étape est optionnelle : les timings sont basés sur la réanalyse avec prompt, mais pour les chansons multilingues, il est toujours recommandé d'exécuter d'abord transcribe_mixed.py pour voir la carte des langues et déterminer quelle fenêtre utiliser --lang en ou --lang ja.

3. Écrire le fichier source des paroles (cette étape doit être faite manuellement)

Déterminez d'abord le chemin, puis écrivez <project>/lyrics_source.json.

3A L'utilisateur a fourni des paroles officielles (chemin préféré)

  • Utilisez les paroles officielles sans changer un mot : le champ en est le texte original officiel (anglais pour l'anglais, japonais pour le japonais, kanji/kana tels quels), zh est la traduction phrase par phrase.
  • Les timings ne proviennent pas de la transcription complète : utilisez les paroles officielles comme initial_prompt pour une réanalyse par fenêtre afin d'obtenir des timings au niveau du mot (voir 3.5), chaque ligne a des start/end explicites, align_lyrics.py passera par le canal manuel pour ancrer ligne par ligne.
  • Incohérence entre les paroles officielles et la réanalyse → adoptez toujours les paroles officielles, listez les différences dans NOTES.md pour confirmation par l'utilisateur. Trois types courants : forme standard vs faute de frappe (不甲斐ない / 不甲埋ない), mots à prononciation similaire (束の間の / 明日の間の), consonne sourde mal entendue (smiling / falling).
  • Dans les paroles officielles, si deux lignes sont chantées d'une traite et font moins d'une seconde chacune → fusionnez les sous-titres en une seule ligne (texte inchangé, simplement côte à côte), écrivez la table de fusion dans NOTES.md.
  • Onomatopées ou improvisations non présentes dans les paroles officielles ("Yeah,", fredonnement, sifflement) → pas de sous-titres, n'inventez pas.
  • Structure à suivre :
{
  "audio": "Artist - Title.mp3",
  "models": ["large-v3-turbo — prompted window re-scans, official lyrics as initial_prompt"],
  "lines": [
    {"en": "Oh my god, they're coming again", "zh": "哦天哪,他们又来了", "start": 6.36, "end": 9.10, "lang": "en", "conf": "high"}
  ]
}

3B Pas de paroles officielles (chemin de reconstruction)

Lisez whisper_raw.json (ou whisper_mixed.json pour les chansons multilingues) et écrivez le fichier source :

{
  "audio": "Artist - Title.mp3",
  "models": ["faster-whisper medium.en — full track, word timestamps"],
  "lines": [
    {"en": "Sometimes I lay under the moon", "zh": "有时我躺卧在月光之下"},
    {"en": "And thank God I'm breathing", "zh": "感谢上天让我仍在呼吸"}
  ]
}

Exigences communes aux deux chemins :

  • Ligne = une phrase réellement chantée, selon la ponctuation officielle ; les phrases trop longues fusionnées par Whisper doivent être divisées.
  • Orthographe anglaise corrigée selon les paroles officielles (conservez les apostrophes comme 'Cause / I've), ne recopiez pas les erreurs de Whisper.
  • Traduction phrase par phrase en chinois, avec le ton de la chanson, pas de saut de phrase, pas de fusion, pas de texte factice.
  • Les refrains répétés doivent être écrits à chaque occurrence (pas de « idem »).
  • Si une phrase vocale est couverte par l'accompagnement et que l'alignement automatique est clairement décalé, ajoutez-lui un timing explicite (écoutez l'audio avant de remplir) : {"en": "...", "zh": "...", "start": 13.22, "end": 16.80}.
  • Chansons chinoises / instrumentales : pour les chansons chinoises, mettez le texte original dans en et laissez zh vide, une seule ligne s'affiche ; ce skill ne s'applique pas à la musique instrumentale.
  • Chansons multilingues : le champ en contient le texte original dans la langue réelle de la phrase (anglais pour l'anglais, japonais pour le japonais, kanji/kana tels quels), zh contient la traduction en chinois. L'affichage est naturellement « original + chinois » sur deux lignes, le mélange ne casse pas la mise en page ; la ligne anglaise du modèle inclut déjà Yu Gothic UI / Yu Gothic / Meiryo en fallback, les kana et kanji s'afficheront correctement.

3.5 Réanalyse avec prompt : moyen essentiel pour la précision des timings

La transcription complète est souvent imprécise pour les chansons rapides, les chants superposés ou les paroles débitées rapidement. Utiliser les paroles connues comme initial_prompt pour une réanalyse par fenêtre est la méthode la plus précise — la qualité du prompt détermine directement la précision de la réanalyse : paroles officielles > paroles devinées > pas de prompt. On peut l'écrire dans rescan_all.sh pour l'exécuter en batch sur la chanson entière :

"$PY" "$SK/scripts/rescan.py" "<project>" --from 6.0 --to 20.0 \
    --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo" \
    --lang en --prompt "<paroles_officielles_de_cette_fenêtre>"

Points importants :

  • Découpez la chanson entière en fenêtres de 20-26 s avec un chevauchement d'environ 0,5 s, réanalysez chaque fenêtre ; large-v3-turbo sur CPU int8 prend environ 5-10 s par fenêtre.
  • Pour les chansons multilingues, réanalysez chaque fenêtre deux fois (en/ja) : n'utilisez que les timings au niveau du mot qui sont cohérents entre les deux passes ; pour les mots qui n'apparaissent que dans une seule passe, vérifiez avec l'autre passe.
  • Pour les phrases dont le point de départ est incertain ou en avance, ajoutez une fenêtre étroite de 2 s pour verrouiller (ex : --from 37.2 --to 39.2 ne verrouille que le début d'une phrase) ; le point de départ des fenêtres de section peut être faussé par la fin de la phrase précédente.
  • Gestion des hallucinations : la réanalyse produit parfois par hasard 15+ répétitions de la même phrase entière → invalidez cette fenêtre, passez à un autre canal de langue ou réduisez la fenêtre pour réanalyser, ne conservez que les timings uniques et propres, n'écrivez pas les hallucinations dans le fichier source des paroles.
  • Chaque réanalyse sauvegarde rescan_<from>-<to>.json et imprime le début et la fin de chaque mot dans la fenêtre. C'est un deuxième décodage, pas une estimation ; les nombres doivent être écrits directement dans start/end de lyrics_source.json.
  • Pour les sections couvertes par l'accompagnement, traitées comme ooh, fusionnées en un seul bloc, ou dont les phrases répétées ont été avalées, utilisez cette même méthode pour écrire les valeurs de couverture ; changer de modèle (small.en / medium.en) peut aussi être efficace.

4. Alignement + Génération

"$PY" "$SK/scripts/align_lyrics.py" "<project>"
"$PY" "$SK/scripts/motion.py" "<project>"
"$PY" "$SK/scripts/gen_storyboard.py" "<project>"
"$PY" "$SK/scripts/build_frame.py" "<project>"
"$PY" "$SK/scripts/make_index.py" "<project>"

align_lyrics.py imprime le tableau des timings ligne par ligne et effectue deux vérifications strictes :

  • Si des phrases au début/fin ne correspondent pas du tout → échec immédiat avec erreur, et liste les phrases concernées (ne masque pas avec des timings approximatifs).
  • Si des phrases au milieu ne correspondent pas, si deux phrases ont le même point de départ, ou si une phrase est compressée à moins de 0,5 s → imprime REVIEW et quitte avec le code 2.

Dans ces deux cas, revenez à l'étape 3.5 pour ajouter des valeurs de couverture jusqu'à obtenir OK: every line anchored to a real sung timestamp. Ne sautez pas cette étape pour lancer le rendu. Les lignes du chemin 3A ont toutes des start/end explicites (canal manuel), elles doivent toutes être ancrées avec 0 gap-filled ; les lignes du chemin 3B reposent sur la correspondance de mots, les lignes non correspondantes doivent être complétées par des timings selon 3.5.

La graine aléatoire de motion.py est déterminée par « nom de l'artiste + titre de la chanson » — pour une même chanson, le chemin est identique à chaque exécution, différent pour chaque chanson.

5. Vérification

cd "<project>"
node "$HF/packages/cli/bin/hyperframes.mjs" check .
node "$HF/packages/cli/bin/hyperframes.mjs" snapshot . --at "3,20,60,120" --no-end -o build/shots

Doit être respecté : lint / runtime / layout / motion 0 erreur, contrast passe WCAG AA. Regardez ensuite les captures d'écran : l'objet en verre est-il complet ? Les paroles sont-elles centrées ? Le groupe d'animaux est-il en bas ? Y a-t-il des bulles ou des étiquettes de section superflues ? composition_file_too_large est un avertissement de style (fichier de composition > 300 lignes) acceptable pour un design à timeline unique.

6. Rendu + Réception

node "$HF/packages/cli/bin/hyperframes.mjs" render . --skill=music-to-video -q delivery -o renders/video.mp4 --fps 30
"$PY" "$SK/scripts/verify.py" "<project>"

verify.py vérifie la résolution/fréquence d'images/durée (une erreur de plus d'une image signale une erreur) et génère une planche contact. Vous devez regarder la planche contact, confirmez que le début, les couplets, les refrains, les sections répétées et la fin sont tous représentés, et qu'il n'y a pas de trous ou de décalages dans les sous-titres.

Enfin, écrivez NOTES.md (spécifications, source des timings, commandes de reproduction, enregistrement de la vérification) et livrez le fichier final et la planche contact à l'utilisateur.

Règles strictes

  • N'utilisez pas la grille BPM/tempo pour déduire les timings des paroles ; les timestamps ne peuvent provenir que des mesures réelles de Whisper (y compris la réanalyse avec prompt) ou d'une couverture par écoute humaine.
  • Les paroles officielles fournies par l'utilisateur ont priorité sur tout résultat de reconstruction de modèle ; en cas de conflit, adoptez les paroles officielles et listez les différences dans NOTES.md pour confirmation par l'utilisateur.
  • Ne modifiez pas la résolution, la fréquence d'images, la durée, les crédits ou la position des sous-titres parce que « cela semble mieux ».
  • Ne déclarez pas la synchronisation audio-vidéo sans vérification ; chaque chanson doit être échantillonnée pour inspection.
  • Ressources manquantes, outils indisponibles, conflits de spécifications → signalez clairement, n'utilisez pas de données estimées pour faire semblant.
  • Les projets déjà livrés et leurs fichiers source sont considérés comme en lecture seule ; toute modification doit être effectuée dans un nouveau répertoire.

Dépendances d'environnement

  • HyperFrames : node <HF>/packages/cli/bin/hyperframes.mjs (inclut skills/music-to-video/scripts/analyze-beatgrid.py).
  • Python : faster-whisper, librosa, soundfile, numpy, scipy, pillow. En cas d'absence : python -m venv <env> && <env>/Scripts/pip install faster-whisper librosa soundfile numpy scipy pillow.
  • Modèle Whisper : passer directement le nom du modèle le télécharge automatiquement ; on peut aussi pointer vers un répertoire local (couramment utilisé sur cette machine : C:\Users\Admin\.cache\whisper-manual\medium.en ; pour la réanalyse avec prompt, préférez C:\Users\Admin\.cache\whisper-manual\large-v3-turbo qui prend environ 48 s pour la chanson entière sur CPU int8, 5-10 s par fenêtre).
  • ffmpeg / ffprobe doivent être dans le PATH.

Pièges connus

  • N'utilisez pas <video> pour la couche du groupe d'animaux : hyperframes render sur Windows échoue lors de la liaison du répertoire d'images extraites dans le répertoire de compilation (ENOENT ... __hyperframes_video_frames/*/frame_00001.jpg). Utilisez une feuille de sprite.
  • Les filter: hue-rotate() CSS plein écran laissent des jointures verticales dans le rendu ; utilisez plutôt deux couches de taches lumineuses en fondu croisé.
  • Les modèles HTML avec data-composition-id ne doivent pas être placés dans le répertoire racine du projet (cela déclenche multiple_root_compositions) ; mettez-les dans build/.
  • La police chinoise doit être déclarée explicitement avec @font-face et local("SimSun"), sinon lint génère font_family_without_font_face.
  • Hallucinations de réanalyse : certaines fenêtres peuvent produire 15+ répétitions de la même phrase entière (ex : 「永遠の行方はどこにある?」×15) → invalidez cette fenêtre, changez de canal de langue croisé (en) ou réduisez la fenêtre pour réanalyser, n'écrivez pas les timestamps d'hallucinations dans le fichier source des paroles.
  • Incohérence entre paroles officielles et réanalyse : adoptez les paroles officielles et listez la table de correspondance dans NOTES.md pour confirmation par l'utilisateur, ne modifiez pas le texte officiel de votre propre chef.
  • Lignes de paroles rapides fusionnées : dans les paroles officielles, si deux lignes sont chantées d'une traite et font moins d'une seconde chacune, fusionnez les sous-titres en une seule ligne (texte inchangé, simplement côte à côte), écrivez la table de fusion dans NOTES.md.
  • Échec de chargement des polices en mode headless (Yu Gothic UI signale FAILED lors de l'extraction d'images) pas d'inquiétude : le système trouve généralement la police via src: local(), la police de secours suivante fera également l'affaire ; vérifiez d'abord les captures d'écran avant de décider de traiter.

Notes supplémentaires

  • Le skill est optimisé pour Windows, mais peut être adapté à Linux/Mac en ajustant les chemins.
  • Pour les chansons instrumentales, le skill ne s'applique pas ; signalez-le à l'utilisateur.
  • La graine aléatoire pour le mouvement du verre est déterministe : basée sur le nom de l'artiste et le titre de la chanson, garantissant la reproductibilité.
  • Les scripts de vérification doivent être exécutés dans l'ordre ; ne sautez aucune étape.

Skills associés