Script + voz → vídeo de slides animados (slidegen)
Entradas do usuário (Michał):
- script.txt — o texto completo da narração (pode vir colado na mensagem). Tokens entre colchetes:
[1],[2]… — quadros de slide: o slide n vai de[n]até[n+1]. Limites definidos pelo usuário. Se o script não tiver nenhum, divida por tópico (um pensamento por slide, ~10–40 s).[boss.mp4],[mapa.png]— um arquivo de mídia que o usuário anexa; mostre-o a partir daquele ponto da narração.[qualquer outro texto], ex.:[obrazek z WoW pokazujący Lich Kinga]— uma descrição: encontre conteúdo real correspondente (veja Ativos) e mostre-o a partir daquele ponto.
- nome do jogo — a aparência deve referenciar este jogo direta ou indiretamente; ícones/arte devem vir dele (um nome de arquivo como
ds_broniesugere Dark Souls; confirme pelo script). - gravação de voz (qualquer áudio/vídeo) — pode chegar antes ou depois do script; transcreva-a assim que chegar.
Regra rígida: antes de renderizar qualquer vídeo, mostre 6 direções visuais com sabor do jogo sobre o conteúdo do usuário e aguarde a escolha dele (passo 4). O quadro precisa apenas do script.
Código: GitHub v01d3tr/claude-skills, pasta slidegen/ (o README lá lista os arquivos). script.py tokens → seções → tempos · align.py Parakeet TDT v3 → words.json · spec.json escrito por Claude · render.mjs Playwright Chromium + ffmpeg (apenas janelas em movimento são capturadas, pausas são mantidas, segmentos em cache, quadros) · template.html temas + layouts · icons.py ícones oficiais do WoW · assets.py arte do jogo do GitHub. O código-fonte deste skill é skills/slidegen-video/SKILL.md no mesmo repositório.
1. Configuração (uma vez por sessão; pule se /home/claude/slidegen/render.mjs existir)
- Anexe o repositório com a ferramenta add_repo (proprietário
v01d3tr, repoclaude-skills;access: "push"apenas se mudanças de código forem enviadas) e clone exatamente como a ferramenta disser, para/home/claude/claude-skills. - Instale:
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
Se o repositório não puder ser acessado e o usuário anexou slidegen.zip, descompacte-o em /home/claude/. Playwright + Chromium estão pré-instalados. Do shell, HuggingFace, Wowhead, wikis, Fandom e CDNs de jogos estão bloqueados; GitHub (git, API search, releases) e npm/PyPI funcionam.
2. Leia o script
mkdir -p /home/claude/proj && cd /home/claude/proj && cp "<upload do script>" script.txt # ou escreva o texto colado; mais quaisquer arquivos de mídia que o usuário anexou
python3 /home/claude/slidegen/script.py split script.txt # seções, contagens de palavras, durações aproximadas, tokens de mídia/descrição, arquivos FALTANDO
Arquivos de mídia faltando → peça ao usuário para anexá-los (continue enquanto isso). Se a gravação já estiver lá, execute o passo 5 align.py + script.py align agora: mostra quais partes do script foram realmente faladas — não coloque conteúdo não falado nos slides.
3. Planeje os slides, encontre ativos, escreva spec.json
O usuário prefere planejar primeiro: envie um breve resumo (slide n → título, layout, itens principais, mídia) antes de refinar, a menos que ele tenha dito para ir direto. O resumo pode ir junto com o quadro de estilo (passo 4).
- Um slide por quadro
[n]. Um token[arquivo]/[descrição]dentro de um quadro se torna um slide de mídia começando naquela palavra; se o quadro continuar > ~8 s após o término de um clipe, adicione um slide de conteúdo após ele ("at": "<frase>"). - Inícios de slide:
"mark": "3"para[3],"mark": "m:boss.mp4"para arquivos,"mark": "d:1"… para descrições em ordem (chaves impressas porscript.py). Sem marcas[n]use"at": "<primeiras palavras do tópico>". - Itens entram na palavra em que o narrador os nomeia:
"at": "<1–3 palavras distintivas>"(correspondência difusa; pesquisado a partir do início do slide). Escolha palavras que o ASR acerta (verifique transcript.txt), não nomes próprios distorcidos. - Títulos ≤ ~26 chars (reduzidos automaticamente), legendas ≤ ~35, ≤ 5 ícones por linha, ≤ 4 cards (3 com uma figura). Polonês com diacríticos corretos; slides resumem, nunca transcrevem. Soletre nomes do script, nunca do ASR.
- Uma entidade por slide (arma, classe, chefe, build) → layout
feature; quando a narração nomeia um personagem/inimigo/NPC, adicione suafigurede corpo inteiro naquele momento (o usuário gostou disso). - Os campos de aparência (
theme,vars,bgImage,fonts) vêm da direção que o usuário escolher no passo 4.
Formato do spec (exemplo de trabalho completo: 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": [ /* as 6 direções, passo 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" }
]
}
- Formas de cue:
"at": "frase","at": 12.5,{"at": "frase", "offset": -0.3};"mark"(+"markLead", padrão 0,25 s). Itens sem cue aparecem em cascata após o cabeçalho; mantenha a ordem na tela = ordem da lista (useoffsetse um item posterior fosse entrar antes). - Layouts:
hero(título grande + subtítulo) ·icons(linha de tiles, label + legenda;off: truecinza + riscado) ·cards(ícone opcional, legenda, badge) ·feature(feature: {icon, label, caption, tone, at}tile grande à esquerda + cards à direita;figure: {src, label, caption, at}opcional retrato emoldurado alto surgindo no seu cue à extrema direita,--fig-pos= object-position) ·meter(marcador move-se para ovaluede cada card 0–1, cards anteriores escurecem; um segundo slide de meter pode continuar) ·stats(números grandes) ·media(imagem ou clipe; título/kicker opcionais;"fit": "full","contain": true,"kenburns": true; clipes:"clip": [i,f],"audio": true+volume(padrão 0,35) mistura som do clipe sob a voz, senão mudo;"mediaAt"atrasa). tone: arcane, fire, frost, nature, holy, shadow, danger, neutral.
Ativos — conteúdo real do jogo nomeado
- Ícones do WoW:
python3 /home/claude/slidegen/icons.py find frostbolt lichking;icons.py get /home/claude/proj/icons <nome>…(64×64, ≈14k ícones oficiais deWeakThorr/wowinterfaceicons, uso não comercial por fãs). Especializações de mago: arcanespell_holy_magicalsentry, firespell_fire_firebolt02, frostspell_frost_frostbolt02; chefes geralmenteachievement_boss_*. Se não tiver certeza de um nome → WebSearch " wowhead". - Outros jogos / arte maior:
python3 /home/claude/slidegen/assets.py search "<game> icons" "<game> item icons" "<game> assets" "<game> wiki" "<game> fan site" "<game> landing page" "<game> loading screens";assets.py readme proprietário/repo(dump oficial vs. feito por fã);assets.py ls proprietário/repo <regex>;assets.py get proprietário/repo /home/claude/proj/art <caminho>…. Repositórios de wiki de fã / site de fã / landing page são a melhor fonte de screenshots, arte de área e renders de personagens — pesquise com o assunto em vários idiomas (black|knight|caballero|rycerz). Também npm (curl -s "https://registry.npmjs.org/-/v1/search?text=<jogo>%20icons&size=20"). - Fontes conhecidas — WoW:
Jestokyzz/mod-loading-screen-16x9(88 telas de carregamento clássico/TBC/WotLK 1920×1080, remasterizadas por fãs, com moldura + logo),Zogmaw/encounter-journal-images. Dark Souls 1:SlendyMawn/DarkSoulsItemIcons(todos os ícones de item do 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 corpo inteiro no conjunto, ex.:black-knight-set.jpg= Cavaleiro Negro, 180×342 → upscale 3× Lanczos + nitidez leve),LeaGaj04/dark-souls-hub(public/: fogueira 4K44.jpg,Mapa_Lordran.webp,gwyn.jpg,artorias.jpg,solaire.jpg,OrnsteinSmough.jpg),ABDUSSALAM0005/dark-souls-ui(src/background.pngpergaminho escuro, renders de classe). - Ícones de item transparentes (estilo Souls):
varsdo jogo"--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". Ícones do WoW mantêm os padrões (corte de borda de 8%). - Imagens com moldura/logo do jogo como slide de mídia: pré-corte para a banda de arte com PIL (telas WotLK 1920×1080:
crop((437,340,1482,928))→ 1152×648); comobgImageuse--bgart-size: 200% auto; --bgart-pos: 50% 70%. Nenhum logo pode aparecer. - Sempre Leia cada imagem obtida e confirme que ela mostra o assunto. Nunca gere/desenhe um substituto apresentado como arte do jogo; nunca image_search personagens de jogo.
- Não encontrado → melhor fallback real (arte de área, figura de conjunto de armadura, ícone em um card) + liste as lacunas com links (WebSearch) para que o usuário possa anexar arquivos.
- Informe o usuário uma vez de onde veio a arte (nomes dos repositórios; diga quando for site de fã/remaster) e que é PI do editor sob termos de conteúdo de fã. game-icons.net (
gi:<nome>, CC BY 3.0, crédito) apenas para conceitos genéricos.
4. Quadro de estilo — 6 direções com sabor do jogo, obrigatório antes de qualquer renderização
Construa spec.boardThemes (máx. 6) {name, base, bgImage, fonts, vars}; vars do jogo permanecem em spec.vars. Conjuntos trabalhados: Dark Souls (no exemplo spec — o usuário escolheu 2 · Mapa Lordranu: pergaminho + mapa de Lordran em --bgart-op .17 + Marcellus SC) e WoW (Karazhan / Questlog / Nexus / Arena / Kirin Tor / Icecrown nas telas de carregamento do WoW). Construa um conjunto novo por jogo e tópico. Regras:
- Direção = estrutura base + paleta derivada do jogo (
vars) + arte de fundo real opcional (bgImage, ajustado com--bgart-op/-blur/-bright/-sat/-size/-pos) + fonte opcional. Nomeie-a após um lugar, facção, elemento ou peça de UI do jogo. - ≥ 4 de 6 usam arte real do jogo como fundo ou imitam uma peça de UI reconhecível do jogo (registro de quest, inventário, mapa, moldura de tela de carregamento). Todas as 6 claramente diferentes (centralizado/alinhado à esquerda, claro/escuro, arte diferente).
- Bases claras com arte movimentada:
--bgart-op≈ .17, mais escuro--muted; defina--fcap-color(legenda do feature) para um acento escuro — cores de tom são feitas para cards escuros. - Fontes apenas com
latin-ext(Polonês):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. Não: IM Fell English SC, Orbitron. Outras:npm i -s @fontsource/<f>,"fonts": ["<f>/400.css"], defina--title-font/--label-font. - Bases (
body[data-theme=…]em template.html):grimoireescuro quente dourado Cinzel centralizado ·parchmentclaro papel, títulos vermelho-escuro, cards escuros ·arcanebrilho índigo/turquesa, Rajdhani ·esportscarvão, Oswald, alinhado à esquerda, kicker tag ·codexclaro editorial Cormorant, alinhado à esquerda ·frostforgeaço frio azul, branco-gelo Cinzel. Adicione uma base se um jogo precisar.
Execute nos 2 slides mais representativos (layouts diferentes; adicione um slide de mídia se o script depender deles):
cd /home/claude/slidegen && node render.mjs /home/claude/proj/spec.json --board 1,3 # funciona sem gravação
Leia proj/build/board_*.jpg primeiro (transbordamento, texto sobre arte, vazamento de logo, ícones errados, baixo contraste), corrija, então SendUserFile ambos + o resumo, peça um número ou uma mistura. Pare e aguarde. Em seguida, copie a direção escolhida para o nível superior do spec: theme = base, vars = {...spec.vars, ...direction.vars}, bgImage, fonts.
5. Alinhe a gravação, renderize
cd /home/claude/proj
ffmpeg -v error -y -i "<upload da gravação>" -vn -ac 1 -ar 44100 voice.wav
python3 /home/claude/slidegen/align.py voice.wav words.json # ~0,1× tempo real; escreve transcript.txt
python3 /home/claude/slidegen/script.py align script.txt words.json # marks.json; verifique "low confidence" / "NOT FOUND"
cd /home/claude/slidegen
node render.mjs /home/claude/proj/spec.json --cues # todos os tempos; corrija "Cue not found" / correspondências difusas estranhas
node render.mjs /home/claude/proj/spec.json --preview 12.4,95.2 # momento mais completo de cada slide → build/preview_*.jpg, Leia-os
node render.mjs /home/claude/proj/spec.json --budget 540 # primeiro plano, timeout 600000; saída 3 = PARCIAL → execute novamente até completar
Ad-libs são ok (alinhamento pula palavras não correspondentes); uma marca NOT FOUND recebe "at" com uma frase de transcript.txt. Um vídeo movimentado de 1 min renderiza em ~40 s; palestras longas são principalmente pausas (≈25–35 min por 40 min). Edições no spec re-renderizam apenas as partes alteradas (Playwright faz cache de segmentos de áudio não alterados e quadros de slides; ver build/cached/).
Durante a renderização: execute while true; do clear; cat build/status.txt 2>/dev/null || echo 'Aguardando…'; sleep 3; done para monitorar o progresso. O status mostra "Gravando slide n", "Renderizando", "Mesclando", "Finalizado". O stderr do ffmpeg pode imprimir avisos de fim de mídia — eles são seguros (a tela preta com áudio aparece até a última fala). Se o tempo estourar (render.mjs trava), mate o processo Node e execute node render.mjs /home/claude/proj/spec.json --budget 540 novamente — ele retoma.
6. Entregue
out.mp4 codificado com x264, áudio AAC, pronto para upload. Versão curta (agora para verificação): ffmpeg -i out.mp4 -c copy -map 0 -segment_time 5 -f segment out_%03d.mp4; envie out_000.mp4 para o usuário. O vídeo completo por upload direct (se ≤ 100 MB) ou /home/claude/slidegen/split.sh out.mp4 → pasta chunks/ → um por um. Aponte para #slidegen:matrix.org (canal Discord/Matrix) para feedback.
Verifique: sem postura de marketing (wow!, incrível!), sem conselhos do tipo "aqui estão algumas ideias", sem sugerir que o usuário aguarde — apenas "Tudo pronto." + arquivo(s).