Guion + voz → video de diapositivas animadas (slidegen)
Entradas del usuario (Michał):
- script.txt — el texto completo de la narración (puede pegarse en el mensaje). Tokens entre corchetes:
[1],[2]… — marcos de diapositiva: la diapositiva n va desde[n]hasta[n+1]. Límites estrictos elegidos por el usuario. Si el guion no los tiene, dividir por tema (una idea por diapositiva, ~10–40 s).[boss.mp4],[mapa.png]— un archivo multimedia que el usuario adjunta; mostrarlo desde ese punto de la narración.[cualquier otro texto], p. ej.[imagen de WoW mostrando al Rey Exánime]— una descripción: encontrar contenido real que coincida (ver Recursos) y mostrarlo desde ese punto.
- nombre del juego — el aspecto debe referenciar este juego directa o indirectamente; los iconos/arte deben ser de él (un nombre de archivo como
ds_broniesugiere Dark Souls; confirmar con el guion). - grabación de voz (cualquier audio/video) — puede llegar antes o después del guion; transcribirla tan pronto como llegue.
Regla estricta: antes de renderizar cualquier video, mostrar 6 direcciones visuales con sabor al juego sobre el contenido del usuario y esperar su elección (paso 4). El tablero solo necesita el guion.
Código: GitHub v01d3tr/claude-skills, carpeta slidegen/ (README allí enumera los archivos). script.py tokens → secciones → tiempos · align.py Parakeet TDT v3 → words.json · spec.json escrito por Claude · render.mjs Playwright Chromium + ffmpeg (solo ventanas en movimiento capturadas, retenciones en otros lugares, segmentos en caché, tableros) · template.html temas + diseños · icons.py iconos oficiales de WoW · assets.py arte del juego desde GitHub. El código fuente de esta habilidad es skills/slidegen-video/SKILL.md en el mismo repositorio.
1. Configuración (una vez por sesión; omitir si /home/claude/slidegen/render.mjs existe)
- Adjuntar el repositorio con la herramienta add_repo (propietario
v01d3tr, repoclaude-skills;access: "push"solo si se enviarán cambios de código) y clonarlo exactamente como dice la herramienta, en/home/claude/claude-skills. - Instalar:
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 no se puede acceder al repositorio y el usuario adjuntó slidegen.zip, descomprimirlo en /home/claude/. Playwright + Chromium están preinstalados. Desde el shell, HuggingFace, Wowhead, wikis, Fandom y los CDN de juegos están bloqueados; GitHub (git, búsqueda API, lanzamientos) y npm/PyPI funcionan.
2. Leer el guion
mkdir -p /home/claude/proj && cd /home/claude/proj && cp "<subida del guion>" script.txt # o escribir el texto pegado; más cualquier archivo multimedia que el usuario haya adjuntado
python3 /home/claude/slidegen/script.py split script.txt # secciones, conteos de palabras, duraciones aproximadas, tokens de medios/descripción, archivos FALTANTES
Archivos multimedia faltantes → pedir al usuario que los adjunte (continuar mientras tanto). Si la grabación ya está, ejecutar el paso 5 align.py + script.py align ahora: muestra qué partes del guion se hablaron realmente — no poner contenido no hablado en las diapositivas.
3. Planificar diapositivas, encontrar recursos, escribir spec.json
El usuario prefiere planificar primero: enviar un breve esquema (diapositiva n → título, diseño, elementos clave, medios) antes de pulir, a menos que diga que solo continúe. El esquema puede ir junto con el tablero de estilo (paso 4).
- Una diapositiva por cada marco
[n]. Un token[archivo]/[descripción]dentro de un marco se convierte en una diapositiva de medios que comienza en esa palabra; si el marco continúa > ~8 s después de que termina un clip, añadir una diapositiva de contenido después ("at": ""). - Inicios de diapositiva:
"mark": "3"para[3],"mark": "m:boss.mp4"para archivos,"mark": "d:1"… para descripciones en orden (claves impresas porscript.py). Sin marcas[n]usar"at": "<primeras palabras del tema>". - Los elementos aparecen en la palabra donde el narrador los nombra:
"at": "<1–3 palabras distintivas>"(coincidencia difusa; buscadas desde el inicio de la diapositiva). Elegir palabras que el ASR reconozca bien (revisar transcript.txt), no nombres propios deformados. - Títulos ≤ ~26 caracteres (autoacortados), leyendas ≤ ~35, ≤ 5 iconos por fila, ≤ 4 tarjetas (3 con una figura). Polaco con diacríticos correctos; las diapositivas resumen, nunca transcriben. Escribir los nombres del guion, nunca del ASR.
- Una entidad por diapositiva (arma, clase, jefe, build) → diseño
feature; cuando la narración nombre a un personaje/enemigo/NPC, añadir sufigurede cuerpo completo en esa señal (al usuario le gustó esto). - Los campos de aspecto (
theme,vars,bgImage,fonts) provienen de la dirección que el usuario elija en el paso 4.
Formato del spec (ejemplo completo funcional: slidegen/examples/dark-souls-bronie/spec.json):
{
"series": "Dark Souls · mejores armas PvE",
"theme": "parchment", "vars": { "--accent": "#8c2a17" }, "bgImage": "art/Mapa_Lordran.webp", "fonts": ["marcellus-sc/400.css"],
"boardThemes": [ /* las 6 direcciones, paso 4 */ ],
"audio": "voice.wav", "words": "words.json", "marks": "marks.json", "output": "out.mp4", "lead": 0.12,
"slides": [
{ "mark": "1", "section": "1/4 Introducción", "kicker": "Dark Souls · PvE", "title": "Mejores armas", "layout": "icons",
"items": [ { "icon": "icons/Zweihander.png", "tone": "fire", "label": "Zweihander", "caption": "fuerza" } ],
"note": { "at": "según el estilo", "text": "división según el estilo de juego" } },
{ "mark": "3", "kicker": "Favorito de los speedrunners", "title": "Black Knight Halberd", "layout": "feature",
"feature": { "icon": "icons/Black Knight Halberd.png", "tone": "danger", "label": "BK Halberd", "caption": "quality / fuerza" },
"figure": { "src": "art/black-knight-figure.jpg", "label": "Caballero Negro", "caption": "Darkroot Basin", "at": "del caballero negro" },
"items": [ { "at": "del caballero negro", "icon": "icons/Black Knight Helm.png", "tone": "shadow", "label": "Drop del Caballero Negro", "caption": "drop raro" } ] },
{ "mark": "m:boss.mp4", "layout": "media", "src": "boss.mp4", "caption": "Enfrentamiento con el jefe", "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": "subir de nivel", "value": 0.14, "tone": "nature", "label": "Subir de nivel", "caption": "simple y seguro" } ] },
{ "at": "talentos", "layout": "stats", "items": [ { "at": "décimo", "label": "10", "caption": "primer punto" } ] },
{ "at": "resumiendo", "layout": "hero", "kicker": "Resumen", "title": "Buscamos magos", "subtitle": "servidor PvP, Horda" }
]
}
- Formas de señal:
"at": "frase","at": 12.5,{"at": "frase", "offset": -0.3};"mark"(+"markLead", por defecto 0.25 s). Los elementos sin señal se escalonan después del encabezado; mantener en pantalla el orden de la lista (usaroffsetsi un elemento posterior apareciera antes). - Diseños:
hero(título grande + subtítulo) ·icons(fila de fichas, etiqueta + leyenda;off: truegris + tachado) ·cards(icono opcional, leyenda, insignia) ·feature(feature: {icon,label,caption,tone,at}ficha grande a la izquierda + tarjetas a la derecha; opcionalfigure: {src,label,caption,at}retrato alto con marco que aparece en su señal a la derecha,--fig-pos= object-position) ·meter(marcador se mueve alvalue0–1 de cada tarjeta, tarjetas anteriores se atenúan; una segunda diapositiva de medidor puede continuar) ·stats(números grandes) ·media(imagen o clip; título/kicker opcional;"fit": "full","contain": true,"kenburns": true; clips:"clip": [i,f],"audio": true+volume(por defecto 0.35) mezcla el sonido del clip debajo de la voz, de lo contrario silenciado;"mediaAt"lo retrasa). tone: arcane, fire, frost, nature, holy, shadow, danger, neutral.
Recursos — contenido real del juego nombrado
- Iconos de WoW:
python3 /home/claude/slidegen/icons.py find frostbolt lichking;icons.py get /home/claude/proj/icons <nombre>…(64×64, ≈14k iconos oficiales deWeakThorr/wowinterfaceicons, uso no comercial para fans). Especializaciones de mago: arcanospell_holy_magicalsentry, fuegospell_fire_firebolt02, escarchaspell_frost_frostbolt02; jefes a menudoachievement_boss_*. Si no está seguro de un nombre → WebSearch " wowhead". - Otros juegos / arte más grande:
python3 /home/claude/slidegen/assets.py search "<juego> icons" "<juego> item icons" "<juego> assets" "<juego> wiki" "<juego> fan site" "<juego> landing page" "<juego> loading screens";assets.py readme owner/repo(volcado oficial vs. hecho por fans);assets.py ls owner/repo <regex>;assets.py get owner/repo /home/claude/proj/art <ruta>…. Los repositorios de wikis de fans / sitios de fans / páginas de aterrizaje son la mejor fuente de capturas de pantalla, arte de áreas y renders de personajes — buscar con grep el tema en varios idiomas (black|knight|caballero|rycerz). También npm (curl -s "https://registry.npmjs.org/-/v1/search?text=<juego>%20icons&size=20"). - Fuentes conocidas — WoW:
Jestokyzz/mod-loading-screen-16x9(88 pantallas de carga clásicas/TBC/WotLK 1920×1080, rehechas por fans, con marco + logotipo),Zogmaw/encounter-journal-images. Dark Souls 1:SlendyMawn/DarkSoulsItemIcons(todos los iconos de objetos de DSR, PNG transparente ~185 px,Weapons/,Armor/,Consumables/…),ozankasikci/dark-souls-wiki(assets/images/{areas,armor,bosses,npcs,weapons,shields,rings,items};armor/*-set.jpg= figura de cuerpo completo con el conjunto, p. ej.black-knight-set.jpg= Caballero Negro, 180×342 → escalar 3× Lanczos + enfoque ligero),LeaGaj04/dark-souls-hub(public/: fogata 4K44.jpg,Mapa_Lordran.webp,gwyn.jpg,artorias.jpg,solaire.jpg,OrnsteinSmough.jpg),ABDUSSALAM0005/dark-souls-ui(src/background.pngpergamino oscuro, renders de clases). - Iconos de objetos transparentes (estilo Souls): vars globales del juego
"--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". Los iconos de WoW mantienen los valores predeterminados (8% de recorte del borde). - Imágenes con marco/logotipo del juego como diapositiva de medios: precortar a la banda de arte con PIL (pantallas WotLK 1920×1080:
crop((437,340,1482,928))→ 1152×648); comobgImageusar--bgart-size: 200% auto; --bgart-pos: 50% 70%. No puede mostrarse ningún logotipo. - Siempre Leer cada imagen obtenida y confirmar que muestra el tema. Nunca generar/dibujar un sustituto presentado como arte del juego; nunca image_search personajes del juego.
- No encontrado → mejor alternativa real (arte de área, figura de conjunto de armadura, icono en una tarjeta) + listar los vacíos con enlaces (WebSearch) para que el usuario pueda adjuntar archivos.
- Decir al usuario una vez de dónde provino el arte (nombres de repositorios; decir cuando es sitio de fans/rehecho) y que es propiedad intelectual del editor bajo términos de contenido para fans. game-icons.net (
gi:<nombre>, CC BY 3.0, crédito) solo para conceptos genéricos.
4. Tablero de estilo — 6 direcciones con sabor al juego, requeridas antes de cualquier renderizado
Construir spec.boardThemes (máx. 6) {name, base, bgImage, fonts, vars}; las vars globales del juego permanecen en spec.vars. Conjuntos ya hechos: Dark Souls (en el spec de ejemplo — el usuario eligió 2 · Mapa de Lordran: pergamino + mapa de Lordran con --bgart-op .17 + Marcellus SC) y WoW (Karazhan / Diario de misiones / Nexo / Arena / Kirin Tor / Corona de Hielo en pantallas de carga de WoW). Construir un conjunto nuevo por juego y tema. Reglas:
- Dirección = estructura base + paleta derivada del juego (
vars) + arte de fondo real opcional (bgImage, ajustado con--bgart-op/-blur/-bright/-sat/-size/-pos) + fuente opcional. Nombrarlo después de un lugar, facción, elemento o pieza de UI del juego. - ≥ 4 de 6 usan arte real del juego como fondo o imitan una pieza reconocible de la UI del juego (diario de misiones, inventario, mapa, marco de pantalla de carga). Las 6 claramente diferentes (centradas/alineadas a la izquierda, claras/oscuras, arte diferente).
- Bases claras con arte ocupado:
--bgart-op≈ .17,--mutedmás oscuro; establecer--fcap-color(leyenda de característica) a un acento oscuro — los colores de tono están hechos para tarjetas oscuras. - Fuentes solo con
latin-ext(polaco):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. No: IM Fell English SC, Orbitron. Otras:npm i -s @fontsource/<f>,"fonts": ["<f>/400.css"], establecer--title-font/--label-font. - Bases (
body[data-theme=…]en template.html):grimoireoscuro cálido oro Cinzel centrado ·parchmentpapel claro, títulos rojo profundo, tarjetas oscuras ·arcanebrillo índigo/verde agua, Rajdhani ·esportscarbón, Oswald, alineado a la izquierda, kicker de etiqueta ·codexeditorial claro Cormorant, alineado a la izquierda ·frostforgeacero frío azul, hielo blanco Cinzel. Añadir una base si un juego lo necesita.
Ejecutar en las 2 diapositivas más representativas (diferentes diseños; añadir una diapositiva de medios si el guion depende de ellas):
cd /home/claude/slidegen && node render.mjs /home/claude/proj/spec.json --board 1,3 # funciona sin grabación
Leer proj/build/board_*.jpg primero (desbordamiento, texto sobre arte, fugas de logotipo, iconos incorrectos, bajo contraste), corregir, luego SendUserFile ambos + el esquema, pedir un número o una combinación. Detenerse y esperar. Luego copiar la dirección elegida al nivel superior del spec: theme = base, vars = {...spec.vars, ...direction.vars}, bgImage, fonts.
5. Alinear la grabación, renderizar
cd /home/claude/proj
ffmpeg -v error -y -i "<subida de la grabación>" -vn -ac 1 -ar 44100 voice.wav
python3 /home/claude/slidegen/align.py voice.wav words.json # ~0.1× tiempo real; escribe transcript.txt
python3 /home/claude/slidegen/script.py align script.txt words.json # marks.json; revisar "baja confianza" / "NO ENCONTRADO"
cd /home/claude/slidegen
node render.mjs /home/claude/proj/spec.json --cues # todos los tiempos; corregir "Cue not found" / coincidencias difusas extrañas
node render.mjs /home/claude/proj/spec.json --preview 12.4,95.2 # momento más completo de cada diapositiva → build/preview_*.jpg, Leerlas
node render.mjs /home/claude/proj/spec.json --budget 540 # primer plano, tiempo de espera 600000; salida 3 = PARCIAL → reejecutar hasta terminar
Los ad-libs están bien (la alineación omite palabras no coincidentes); una marca NO ENCONTRADA obtiene "at" con una frase de transcript.txt. Un video ocupado de 1 minuto se renderiza en ~40 s; charlas largas son principalmente retenciones (≈25–35 min por 40 min). Las ediciones del spec re-renderizan solo los cambios.
...