Communitygithub.com

v01d3tr/slidegen-video

Transformez le script texte et l'enregistrement vocal de l'utilisateur en une vidéo de diapositives animées synchronisées mot à mot avec la narration, dans le style du jeu nommé avec ses icônes et illustrations réelles.

Qu'est-ce que slidegen-video ?

Cette compétence transforme un script texte au format spécifique (avec des marqueurs de diapositives [n], de fichiers média [file] et de descriptions [description]) et un enregistrement vocal en une vidéo de diapositives animées. Elle utilise la reconnaissance vocale (Parakeet TDT via sherpa-onnx) pour aligner chaque mot du script sur la narration, puis génère une vidéo avec des diapositives stylisées selon le thème d'un jeu vidéo spécifique, en utilisant des icônes et des illustrations réelles provenant de sources comme WeakThorr/wowinterfaceicons ou divers dépôts GitHub. Le processus inclut une étape obligatoire de sélection de direction stylistique (6 propositions visuelles) avant le rendu final. La compétence est conçue pour fonctionner avec des jeux comme World of Warcraft et Dark Souls, mais peut être adaptée à d'autres jeux. Elle repose sur une pile technique incluant Python, Node.js, Playwright Chromium et ffmpeg.

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

Demander à votre IA préférée

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

Documentation

Script + voix → vidéo de diapositives animées (slidegen)

Entrées de l'utilisateur (Michał) :

  • script.txt — le texte complet de la narration (peut être collé dans le message). Jetons entre crochets :
    • [1], [2]... — cadres de diapositives : la diapositive n s'exécute de [n] à [n+1]. Limites strictes choisies par l'utilisateur. Si le script n'en a pas, diviser par sujet (une idée par diapositive, ~10–40 s).
    • [boss.mp4], [mapa.png] — un fichier média que l'utilisateur joint ; l'afficher à partir de ce point de la narration.
    • [tout autre texte], p. ex. [obrazek z WoW pokazujący Lich Kinga] — une description : trouver le contenu réel correspondant (voir Ressources) et l'afficher à partir de ce point.
  • nom du jeu — l'apparence doit faire référence à ce jeu directement ou au moins indirectement ; les icônes/illustrations doivent en provenir (un nom de fichier comme ds_bronie fait penser à Dark Souls ; confirmer avec le script).
  • enregistrement vocal (audio ou vidéo) — peut arriver avant ou après le script ; le transcrire dès son arrivée.

Règle stricte : avant de rendre une vidéo, montrer 6 directions visuelles dans le style du jeu sur le propre contenu de l'utilisateur et attendre son choix (étape 4). Le tableau n'a besoin que du script.

Code : GitHub v01d3tr/claude-skills, dossier slidegen/ (le README y liste les fichiers). script.py jetons → sections → temps · align.py Parakeet TDT v3 → words.json · spec.json écrit par Claude · render.mjs Playwright Chromium + ffmpeg (seules les fenêtres en mouvement sont capturées, les autres sont fixes, segments mis en cache, tableaux) · template.html thèmes + mises en page · icons.py icônes officielles WoW · assets.py illustrations de jeux depuis GitHub. Le code source de cette compétence est skills/slidegen-video/SKILL.md dans le même dépôt.

1. Configuration (une fois par session ; ignorer si /home/claude/slidegen/render.mjs existe)

  1. Attacher le dépôt avec l'outil add_repo (propriétaire v01d3tr, dépôt claude-skills ; access: "push" seulement si des modifications de code seront poussées) et le cloner exactement comme indiqué par l'outil, dans /home/claude/claude-skills.
  2. Installer :
cp -r /home/claude/claude-skills/slidegen /home/claude/slidegen && cd /home/claude/slidegen && npm install
pip install -q --break-system-packages sherpa-onnx soundfile numpy
mkdir -p /home/claude/models && cd /home/claude/models && curl -sSL https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8.tar.bz2 | tar xj

Si le dépôt est inaccessible et que l'utilisateur a joint slidegen.zip, le décompresser dans /home/claude/ à la place. Playwright + Chromium sont préinstallés. Depuis le shell, HuggingFace, Wowhead, les wikis, Fandom et les CDN de jeux sont bloqués ; GitHub (git, recherche API, releases) et npm/PyPI fonctionnent.

2. Lire le script

mkdir -p /home/claude/proj && cd /home/claude/proj && cp "<upload du script>" script.txt   # ou écrire le texte collé ; plus les fichiers média joints par l'utilisateur
python3 /home/claude/slidegen/script.py split script.txt   # sections, comptes de mots, ~durées, jetons média/description, fichiers MANQUANTS

Fichiers média manquants → demander à l'utilisateur de les joindre (continuer pendant ce temps). Si l'enregistrement est déjà là, exécuter l'étape 5 align.py + script.py align maintenant : cela montre quelles parties du script ont réellement été prononcées — ne pas mettre de contenu non prononcé sur les diapositives.

3. Planifier les diapositives, trouver les ressources, écrire spec.json

L'utilisateur préfère planifier d'abord : envoyer un bref aperçu (diapositive n → titre, mise en page, éléments clés, média) avant de peaufiner, sauf s'il a dit de simplement y aller. L'aperçu peut aller avec le tableau de style (étape 4).

  • Une diapositive par cadre [n]. Un jeton [file]/[description] à l'intérieur d'un cadre devient une diapositive média commençant à ce mot ; si le cadre se poursuit > ~8 s après la fin d'un clip, ajouter une diapositive de contenu après ("at": "<phrase>").
  • Débuts de diapositives : "mark": "3" pour [3], "mark": "m:boss.mp4" pour les fichiers, "mark": "d:1"... pour les descriptions dans l'ordre (clés imprimées par script.py). Sans marques [n] utiliser "at": "<premiers mots du sujet>".
  • Les éléments sont déclenchés sur le mot où le narrateur les nomme : "at": "<1–3 mots distinctifs>" (correspondance floue ; recherché à partir du début de la diapositive). Choisir des mots que l'ASR reconnaît bien (vérifier transcript.txt), pas des noms propres déformés.
  • Titres ≤ ~26 car. (réduits automatiquement), légendes ≤ ~35, ≤ 5 icônes par ligne, ≤ 4 cartes (3 avec une figure). Polonais avec diacritiques corrects ; les diapositives résument, ne transcrivent jamais. Orthographier les noms du script, jamais de l'ASR.
  • Une entité par diapositive (arme, classe, boss, construction) → mise en page feature ; quand la narration nomme un personnage/ennemi/PNJ, ajouter sa figure en pied à ce déclencheur (l'utilisateur a aimé cela).
  • Les champs d'apparence (theme, vars, bgImage, fonts) proviennent de la direction choisie par l'utilisateur à l'étape 4.

Format du spec (exemple de travail complet : slidegen/examples/dark-souls-bronie/spec.json) :

{
  "series": "Dark Souls · najlepsze bronie PvE",
  "theme": "parchment", "vars": { "--accent": "#8c2a17" }, "bgImage": "art/Mapa_Lordran.webp", "fonts": ["marcellus-sc/400.css"],
  "boardThemes": [ /* les 6 directions, étape 4 */ ],
  "audio": "voice.wav", "words": "words.json", "marks": "marks.json", "output": "out.mp4", "lead": 0.12,
  "slides": [
    { "mark": "1", "section": "1/4 Wstęp", "kicker": "Dark Souls · PvE", "title": "Najlepsze bronie", "layout": "icons",
      "items": [ { "icon": "icons/Zweihander.png", "tone": "fire", "label": "Zweihander", "caption": "siła" } ],
      "note": { "at": "według stylu", "text": "podział według stylu gry" } },
    { "mark": "3", "kicker": "Ulubieniec speedrunnerów", "title": "Black Knight Halberd", "layout": "feature",
      "feature": { "icon": "icons/Black Knight Halberd.png", "tone": "danger", "label": "BK Halberd", "caption": "quality / siła" },
      "figure": { "src": "art/black-knight-figure.jpg", "label": "Czarny Rycerz", "caption": "Darkroot Basin", "at": "czarnego rycerza" },
      "items": [ { "at": "czarnego rycerza", "icon": "icons/Black Knight Helm.png", "tone": "shadow", "label": "Drop z Czarnego Rycerza", "caption": "rzadki drop" } ] },
    { "mark": "m:boss.mp4", "layout": "media", "src": "boss.mp4", "caption": "Walka z bossem", "audio": true, "volume": 0.3, "clip": [12, 30] },
    { "mark": "d:1", "layout": "media", "src": "art/icc_raid.jpg", "kicker": "Raid", "title": "Icecrown Citadel", "kenburns": true },
    { "mark": "4", "layout": "meter", "items": [ { "at": "levelowanie", "value": 0.14, "tone": "nature", "label": "Levelowanie", "caption": "prosty i bezpieczny" } ] },
    { "at": "talenty", "layout": "stats", "items": [ { "at": "dziesiątym", "label": "10", "caption": "pierwszy punkt" } ] },
    { "at": "podsumowując", "layout": "hero", "kicker": "Podsumowanie", "title": "Szukamy magów", "subtitle": "serwer PvP, Horda" }
  ]
}
  • Formes de déclenchement : "at": "phrase", "at": 12.5, {"at": "phrase", "offset": -0.3} ; "mark" (+ "markLead", défaut 0,25 s). Les éléments non déclenchés s'étagent après l'en-tête ; maintenir l'ordre à l'écran = ordre de la liste (utiliser offset si un élément ultérieur se déclencherait plus tôt).
  • Mises en page : hero (grand titre + sous-titre) · icons (rangée de tuiles, étiquette + légende ; off: true grise + barre) · cards (icône optionnelle, légende, badge) · feature (feature: {icon,label,caption,tone,at} grande tuile à gauche + cartes à droite ; figure: {src,label,caption,at} optionnel portrait encadré s'élevant à son déclencheur à l'extrême droite, --fig-pos = object-position) · meter (marqueur se déplace vers la value 0–1 de chaque carte, les cartes précédentes s'assombrissent ; une deuxième diapositive meter peut continuer) · stats (grands nombres) · media (image ou clip ; titre/kicker optionnel ; "fit": "full", "contain": true, "kenburns": true ; clips : "clip": [d,f], "audio": true + volume (défaut 0,35) mélange le son du clip sous la voix, sinon muet ; "mediaAt" le retarde).
  • tone : arcane, fire, frost, nature, holy, shadow, danger, neutral.

Ressources — contenu réel du jeu nommé

  • Icônes WoW : python3 /home/claude/slidegen/icons.py find frostbolt lichking ; icons.py get /home/claude/proj/icons <nom>… (64×64, ≈14 000 icônes officielles de WeakThorr/wowinterfaceicons, utilisation non commerciale par les fans). Spécialisations mages : arcane spell_holy_magicalsentry, fire spell_fire_firebolt02, frost spell_frost_frostbolt02 ; les boss ont souvent achievement_boss_*. En cas de doute sur un nom → WebSearch " wowhead".
  • Autres jeux / illustrations plus grandes : python3 /home/claude/slidegen/assets.py search "<jeu> icons" "<jeu> item icons" "<jeu> assets" "<jeu> wiki" "<jeu> fan site" "<jeu> landing page" "<jeu> loading screens" ; assets.py readme owner/repo (dump officiel vs fait par des fans) ; assets.py ls owner/repo <regex> ; assets.py get owner/repo /home/claude/proj/art <chemin>…. Les dépôts de wikis de fans / sites de fans / pages d'accueil sont la meilleure source de captures d'écran, d'illustrations de zones et de rendus de personnages — grep avec le sujet en plusieurs langues (black|knight|caballero|rycerz). Aussi npm (curl -s "https://registry.npmjs.org/-/v1/search?text=<jeu>%20icons&size=20").
  • Sources connues — WoW : Jestokyzz/mod-loading-screen-16x9 (88 écrans de chargement classique/TBC/WotLK 1920×1080, remasterisés par des fans, avec cadre + logo), Zogmaw/encounter-journal-images. Dark Souls 1 : SlendyMawn/DarkSoulsItemIcons (toutes les icônes d'objets DSR, PNG transparents ~185 px, Weapons/, Armor/, Consumables/…), ozankasikci/dark-souls-wiki (assets/images/{areas,armor,bosses,npcs,weapons,shields,rings,items} ; armor/*-set.jpg = figure en pied dans l'ensemble, p. ex. black-knight-set.jpg = Black Knight, 180×342 → agrandir 3× Lanczos + léger accentuation), LeaGaj04/dark-souls-hub (public/ : feu de camp 4K 44.jpg, Mapa_Lordran.webp, gwyn.jpg, artorias.jpg, solaire.jpg, OrnsteinSmough.jpg), ABDUSSALAM0005/dark-souls-ui (src/background.png parchemin sombre, rendus de classes).
  • Icônes d'objets transparentes (style Souls) : variables globales vars "--icon-crop": "0%", "--icon-pad": "7%", "--icon-fit": "contain", "--tile-bg": "radial-gradient(circle at 50% 42%,#2e2a25 0%,#141210 70%,#0a0908 100%)", "--tile-border": "#4d463c". Les icônes WoW conservent les valeurs par défaut (recadrage de bordure à 8 %).
  • Images avec un cadre/logo de jeu comme diapositive média : prédécouper à la bande d'illustration avec PIL (écrans WotLK 1920×1080 : crop((437,340,1482,928)) → 1152×648) ; comme bgImage utiliser --bgart-size: 200% auto; --bgart-pos: 50% 70%. Aucun logo ne doit apparaître.
  • Toujours lire chaque image récupérée et confirmer qu'elle montre le sujet. Ne jamais générer/dessiner un substitut présenté comme illustration de jeu ; ne jamais image_search les personnages de jeux.
  • Non trouvé → meilleur repli réel (illustration de zone, figure d'armure, icône sur une carte) + lister les lacunes avec des liens (WebSearch) pour que l'utilisateur puisse joindre des fichiers.
  • Informer l'utilisateur une fois de la provenance des illustrations (noms de dépôts ; dire quand il s'agit d'un site de fans/remaster) et qu'il s'agit de la propriété intellectuelle de l'éditeur sous des conditions d'utilisation par les fans. game-icons.net (gi:<nom>, CC BY 3.0, crédit) uniquement pour des concepts génériques.

4. Tableau de style — 6 directions dans le style du jeu, obligatoire avant tout rendu

Construire spec.boardThemes (max 6) {name, base, bgImage, fonts, vars} ; les variables globales du jeu restent dans spec.vars. Ensembles déjà réalisés : Dark Souls (dans l'exemple spec — l'utilisateur a choisi 2 · Mapa Lordranu : parchemin + carte de Lordran à --bgart-op .17 + Marcellus SC) et WoW (Karazhan / Questlog / Nexus / Arena / Kirin Tor / Icecrown sur écrans de chargement WoW). Construire un nouvel ensemble par jeu et sujet. Règles :

  • Direction = structure base + palette dérivée du jeu (vars) + illustration de fond réelle optionnelle (bgImage, ajustée avec --bgart-op/-blur/-bright/-sat/-size/-pos) + police optionnelle. La nommer d'après un lieu, une faction, un élément ou un élément d'interface du jeu.
  • ≥ 4 sur 6 utilisent une illustration de jeu réelle comme fond ou imitent un élément d'interface de jeu reconnaissable (journal de quêtes, inventaire, carte, cadre d'écran de chargement). Toutes les 6 clairement différentes (centré/aligné à gauche, clair/sombre, illustration différente).
  • Bases claires avec illustrations chargées : --bgart-op ≈ .17, --muted plus sombre ; définir --fcap-color (légende de fonctionnalité) sur un accent sombre — les couleurs de ton sont faites pour les cartes sombres.
  • Polices uniquement avec latin-ext (polonais) : ls /home/claude/slidegen/node_modules/@fontsource/<f>/files | grep -c latin-ext > 0. OK : Cinzel, Marcellus SC, Pirata One, Cormorant Garamond, Oswald, Rajdhani, Inter. Pas : IM Fell English SC, Orbitron. Autres : npm i -s @fontsource/<f>, "fonts": ["<f>/400.css"], définir --title-font/--label-font.
  • Bases (body[data-theme=…] dans template.html) : grimoire sombre chaude or Cinzel centré · parchment papier clair, titres rouge foncé, cartes sombres · arcane indigo/cyan lueur, Rajdhani · esports charbon, Oswald, aligné à gauche, kicker tag · codex éditorial clair Cormorant, aligné à gauche · frostforge acier bleu froid, glace blanche Cinzel. Ajouter une base si un jeu en nécessite une.

Exécuter sur les 2 diapositives les plus représentatives (mises en page différentes ; ajouter une diapositive média si le script en dépend) :

cd /home/claude/slidegen && node render.mjs /home/claude/proj/spec.json --board 1,3   # fonctionne sans enregistrement

Lire d'abord proj/build/board_*.jpg (débordement, texte sur l'illustration, fuites de logo, mauvaises icônes, faible contraste), corriger, puis SendUserFile les deux + l'aperçu, demander un numéro ou un mélange. S'arrêter et attendre. Puis copier la direction choisie au niveau supérieur du spec : theme = base, vars = {...spec.vars, ...direction.vars}, bgImage, fonts.

5. Aligner l'enregistrement, rendre

cd /home/claude/proj
ffmpeg -v error -y -i "<upload de l'enregistrement>" -vn -ac 1 -ar 44100 voice.wav
python3 /home/claude/slidegen/align.py voice.wav words.json          # ~0,1× temps réel ; écrit transcript.txt
python3 /home/claude/slidegen/script.py align script.txt words.json  # marks.json ; vérifier "low confidence" / "NOT FOUND"
cd /home/claude/slidegen
node render.mjs /home/claude/proj/spec.json --cues                    # tous les temps ; corriger "Cue not found" / correspondances floues étranges
node render.mjs /home/claude/proj/spec.json --preview 12.4,95.2       # moment le plus chargé de chaque diapositive → build/preview_*.jpg, les lire
node render.mjs /home/claude/proj/spec.json --budget 540              # premier plan, timeout 600000 ; sortie 3 = PARTIAL → relancer jusqu'à terminaison

Les improvisations sont acceptables (l'alignement ignore les mots non appariés) ; une marque NOT FOUND obtient "at" avec une phrase de transcript.txt. Une vidéo chargée d'1 min se rend en ~40 s ; les longs discours sont surtout fixes (≈25–35 min par 40 min). Les modifications du spec ne re-rendent que les diapositives changées (segments mis en cache).

Skills associés