O que Rudywizz-motion faz?
Um renderizador determinístico: cada quadro é computado (Chromium headless + WebGL2) e canalizado para o ffmpeg, portanto a mesma entrada sempre gera o mesmo vídeo. Esta pasta é autocontida:
engine/ cli.mjs (entrada), host.js, timeline.js, camera.js, gl/ (shaders), data/ (mapas), fonts/
styles/ uma pasta por estilo (style.js)
templates/ composições prontas (JSON)
assets/demo/ ilustrações demo originais (CC0)
1. Configuração única (verificar antes do primeiro render)
RM="${CLAUDE_SKILL_DIR}" # a pasta que contém este SKILL.md
[ -f "$RM/engine/cli.mjs" ] || RM=$(ls -dt "${CLAUDE_PLUGIN_ROOT}/skills/rudywizz-motion" ~/.claude/plugins/cache/*/rudywizz-motion/*/skills/rudywizz-motion ~/.claude/skills/rudywizz-motion .claude/skills/rudywizz-motion 2>/dev/null | head -1)
TMP=$(node -p "require('os').tmpdir()") # um diretório temporário que bash e Node entendem (também no Windows)
cd "$RM" && npm install --no-audit --no-fund # instala playwright (a única dependência)
node engine/cli.mjs doctor # Node ✓ ffmpeg ✓ browser ✓ WebGL2 ✓ — cada ✗ mostra seu conserto
Execute renders a partir da pasta do usuário com node "$RM/engine/cli.mjs" … para que caminhos relativos sejam resolvidos ali.
Se a verificação do navegador falhar: npx playwright install chromium (ou defina RM_CHROME=/caminho/para/chrome).
Se o ffmpeg estiver faltando, informe ao usuário como instalá-lo (macOS brew install ffmpeg, Windows winget install ffmpeg, Linux apt install ffmpeg).
2. Escolha o formato do trabalho
| O usuário quer | Faça isso |
|---|---|
| Um texto/título animado | render <estilo> --text "…" |
| Uma animação de mapa / rota | render map-route --set 'route=["İstanbul","Konya"]' |
| Sua imagem desenhada como gravura | render image --image foto.jpg --look engrave --grade sepia --film 0.6 |
| Movimentos de câmera em seu clipe | render clip --clip in.mp4 --camera handheld --set speed='"ramp-mid"' |
| Uma sobreposição transparente para seu editor (lower third, legendas, CTA) | render lower-third --text "Nome / Cargo" --alpha --out nome.mov |
| Um reel / documento / teaser / introdução com várias cenas | init reel.json ou comece a partir de um template, depois edite (seção 4) |
Templates: node engine/cli.mjs templates lista todos com uma descrição de uma linha.
Copie um para junto dos assets do usuário (cp "$RM/templates/<nome>.json" .), edite textos/caminhos, renderize.
3. Fluxo de trabalho (sempre)
- Decida estilo(s), texto, formato (padrão 9:16 1080×1920), câmera, correção de cor.
- Verifique stills primeiro — é barato e detecta problemas de layout:
node "$RM/engine/cli.mjs" still <estilo|comp.json> --at 2.5 --size 540 --out "$TMP/check.png"→ abra o PNG e observe. Verifique 2–3 momentos (início, meio, fim de cada cena). Leia quaisquer linhas dewarning/error: elas nomeiam erros de digitação e sugerem a chave correta. - Renderize:
node engine/cli.mjs render … --out out.mp4 - Verifique:
ffprobe -v error -show_entries format=duration -of csv=p=0 out.mp4e capture um ou dois quadros. - Entregue o arquivo com uma linha de contexto.
Regras práticas
- Texto curto vence: 1–6 palavras por linha, no máximo ~4 linhas. Use
" / "ou\npara quebras de linha. - A capitalização turca é automática quando o texto tem ğ/ş/ı/İ; caso contrário, passe
--lang trpara texto turco (i → İ). - Renders consomem muita CPU: ~0,2–0,5 s por quadro 1080p. Pré-visualize com
--size 540e faça o final em 1080. - Nunca baixe imagens/clipes da web sem a autorização do usuário; use os arquivos dele.
- Sobreposições transparentes:
--alpha --out arquivo.mov(ProRes 4444) ou.webm. - Música:
--audio musica.mp3e--bpm Npara quebeat-cut,lyric-videoe a câmerabeat-punchacompanhem a batida.
4. JSON de Composição
{
"format": "9:16",
"lang": "tr",
"bpm": 96,
"audio": "musica.mp3",
"look": { "grade": "teal-orange", "bloom": 0.3, "grain": 0.05, "leak": 0.2, "aberration": 0.3,
"vignette": 0.3, "film": 0, "weave": 0, "distortion": 0 },
"motionBlur": 1,
"scenes": [
{ "style": "map-route", "route": ["İstanbul", "Kapadokya"], "duration": 6, "camera": "drift",
"transition": { "type": "whip", "duration": 0.45, "dir": "left" } },
{ "clip": "praia.mp4", "in": 3.2, "duration": 2.5, "speed": "ramp-mid", "camera": "handheld",
"overlay": { "style": "captions", "text": "Kaş, Antalya" },
"transition": { "type": "burn", "duration": 0.8 } },
{ "image": "retrato.jpg", "look": { "type": "engrave", "reveal": 3 }, "duration": 4, "camera": "push-in" },
{ "style": "neon-sign", "text": "See you / soon", "duration": 3 }
],
"overlays": [ { "style": "captions", "text": "…", "from": 0, "to": 5 } ]
}
- Tipos de cena:
style(qualquer id de estilo + suas opções),image(caminho daimage, oulayers: [{src, depth}]para paralaxe 2.5D),clip(clip,in,speed: número |ramp-in|ramp-out|ramp-mid),color. - Caminhos são relativos ao arquivo JSON.
transitionfica na cena que está saindo. A próxima cena começadurationsegundos antes desta terminar.overlay= um estilo desenhado sobre aquela cena (move-se com a câmera dela).overlays= fixo sobre tudo, sem correção de cor.- Câmera: nome de preset ou
{ "preset": "drift", "amount": 0.6, "shake": 0.5, "keys": [{ "at": 0, "zoom": 1 }, { "at": 1, "zoom": 1.3, "ease": "outExpo" }] }.
5. Catálogo
Câmeras — static, drift, push-in, pull-out, punch-in, crash-zoom, whip-from-left, whip-from-right, whip-from-top, spin-in, rise, orbit, tilt-reveal, tilt-left, tilt-right, vertigo, handheld, float, beat-punch. O movimento da câmera recebe motion blur automaticamente.
Transições — cut, fade, flash, dip, whip, zoom, spin, glitch, ink, burn, liquid, iris, wipe, blinds, pixelate, leak, cube, ripple, doors, stretch, luma.
Looks (imagens/clipes) — engrave (tinta desenha → hachura → lavagem sépia), sketch, oldphoto, duotone, halftone, posterize, noir. Opções: { "type": "engrave", "reveal": 3, "delay": 0.2, "paper": "#ece0c4", "ink": "#33210f" }.
Grades — none, teal-orange, kodak, fuji, sepia, noir, bleach, cyber, sunset, matte (+ gradeAmount 0–1).
Estilos — execute node engine/cli.mjs list para a lista atual. As opções de cada estilo estão documentadas no início de styles/<id>/style.js (defaults + options).
| Estilo | O que faz | Opções principais |
|---|---|---|
| map-route | Voo de rota no globo / mapa plano / províncias da Turquia, pins + rótulos | route, mode globe·flat·turkey·auto, theme dark·atlas·light, icon, highlight |
| history-title | Contador de ano dourado + título de capítulo | text "1453 / Title / Subtitle", from |
| parchment-letter | Pergaminho queimado, escrita à mão + pena + selo de cera | place, signature, seal |
| murmuration | Bando de estorninhos se dobra formando as palavras | birds, cores do céu |
| led-marquee | Painéis LED de lojas/minibus "kayan yazı" | um painel por linha, colors |
| receipt | Impressora térmica imprime a mensagem, rasga | header, items, total, date |
| ink-bleed | Gotas de tinta se espalham formando as letras | ink, paper |
| halftone-press | Impressão risográfica de duas cores | inkA, inkB, dot |
| signal-tune | TV antiga: neve → cartão de teste → no ar | channel, station |
| inflate | Letras cromadas Y2K de balão | chrome, face |
| orbit-ring | Anéis de texto ao redor de um planeta | um anel por linha |
| beat-cut | Uma palavra carimbada por batida, pôster suíço | bpm, offset |
| lyric-video | Letras acendem palavra por palavra na batida | bpm, times, credit |
| captions | Legendas de reel, palavra ativa em um pill (use --alpha) | times, maxWords, pill, position |
| split-flap | Painel de embarque com flip (tambor turco) | title, cols |
| neon-sign | Tubos de neon em tijolo, um com defeito | colors, broken |
| odometer | Dígitos rolantes contam até um número | text "10000 takipçi", prefix, suffix |
| pixel-quest | Tela de título 8-bit | pixel, subtitle |
| vhs-memory | Visual de fita de vídeo caseira | date, clock |
| Tipo cinético | ||
| word-stack | Pilha de pôster justificada, cada linha entra em largura total | accent, beat, kicker |
| typewriter | Digita tecla por tecla com cursor piscando | theme paper·terminal, speed, prompt |
| scramble | Glifos aleatórios decodificam no texto | font mono·display, resolve, hud |
| ticker-rows | Linhas gigantes rolam em direções alternadas | rows, tilt, speed, accent |
| highlight-quote | Citação aparece, um marcador varre as palavras-chave | author, highlight (words), marker |
| glitch-title | RGB split + datamosh se estabilizam em um título limpo | subtitle, colors, every |
| 3D | ||
| extrude-3d | Letras extrudadas e grossas balançam e giram | face, side, bg, depth |
| cube-spin | Cubo gira face a face, uma linha por face | colors, ink, floor |
| text-tunnel | Voe através de anéis de texto até o título | linha 1 = título, rings, ring, colors |
| retro-grid | Grade synthwave, sol listrado, título cromado | linha 1 cromada, resto script, sky, sun, speed |
| particle-sphere | Esfera de partículas se transforma nas palavras | count, morphAt, colors |
| card-carousel | Anel 3D de cartões pousa na última linha | images (arquivos locais), turns, colors |
| Social & broadcast | ||
| countdown | 3·2·1 com anéis girando, depois o texto | from, tick, accent |
| lower-third | Faixa de nome estilo news/YouTube (use --alpha) | linha 1 nome, linha 2 cargo, theme solid·glass·minimal, position |
| chat-story | Chat de mensagens com bolinhas de digitação | uma mensagem por linha, > = eu, name, theme |
| bar-chart | Corrida de gráfico de barras, valores sobem | items: [["A",10],…], unit, note, source |
| cta-follow | Cursor clica em Seguir, check + confetes | linha 1 handle, linha 2 botão, linha 3 subtítulo, done |
As opções de estilo vão em --set chave=valor (valores JSON: --set 'route=["A","B"]') ou como chaves do objeto da cena.
6. Solução de problemas
unknown place "X"(map-route): use"lat,lon"ou{ "name": "X", "lat": 0, "lon": 0 }.- Texto cortado por um movimento de câmera: diminua o
amountda câmera ou usedrift/float. - Renders lentos:
--size 540para rascunhos. Evite--motion-bluracima de 4 a menos que o usuário queira a melhor qualidade. - Saída branca/vazia: execute
stille leia o erro;doctorverifica WebGL2. - Windows PowerShell / cmd distorcendo
--set 'route=["A","B"]': escreva as opções em um arquivo e use--params opts.json, ou use um JSON de composição. - Texto em inglês que contém um nome turco (ı, ş…) ganha capitalização turca automaticamente; passe
--lang enpara interromper isso.