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_broniefait 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)
- Attacher le dépôt avec l'outil add_repo (propriétaire
v01d3tr, dépôtclaude-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. - 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 parscript.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 safigureen 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 (utiliseroffsetsi 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: truegrise + 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 lavalue0–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 deWeakThorr/wowinterfaceicons, utilisation non commerciale par les fans). Spécialisations mages : arcanespell_holy_magicalsentry, firespell_fire_firebolt02, frostspell_frost_frostbolt02; les boss ont souventachievement_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 4K44.jpg,Mapa_Lordran.webp,gwyn.jpg,artorias.jpg,solaire.jpg,OrnsteinSmough.jpg),ABDUSSALAM0005/dark-souls-ui(src/background.pngparchemin 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) ; commebgImageutiliser--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,--mutedplus 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) :grimoiresombre chaude or Cinzel centré ·parchmentpapier clair, titres rouge foncé, cartes sombres ·arcaneindigo/cyan lueur, Rajdhani ·esportscharbon, Oswald, aligné à gauche, kicker tag ·codexéditorial clair Cormorant, aligné à gauche ·frostforgeacier 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).