¿Qué hace Rudywizz-motion?
Un renderizador determinista: cada fotograma se calcula (Chromium sin interfaz + WebGL2) y se envía a ffmpeg, por lo que la misma entrada siempre produce el mismo vídeo. Esta carpeta es autocontenida:
engine/ cli.mjs (entrada), host.js, timeline.js, camera.js, gl/ (shaders), data/ (mapas), fonts/
styles/ una carpeta por estilo (style.js)
templates/ composiciones prediseñadas (JSON)
assets/demo/ ilustraciones demo originales (CC0)
1. Configuración única (verificar antes del primer render)
RM="${CLAUDE_SKILL_DIR}" # la carpeta que contiene 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()") # un directorio temporal en el que bash y Node coinciden (también en Windows)
cd "$RM" && npm install --no-audit --no-fund # instala playwright (la única dependencia)
node engine/cli.mjs doctor # Node ✓ ffmpeg ✓ browser ✓ WebGL2 ✓ — cada ✗ muestra su solución
Ejecute los renders desde la carpeta del usuario con node "$RM/engine/cli.mjs" … para que las rutas relativas se resuelvan allí.
Si falla la verificación del navegador: npx playwright install chromium (o configure RM_CHROME=/ruta/al/chrome).
Si falta ffmpeg, indique al usuario cómo instalarlo (macOS brew install ffmpeg, Windows winget install ffmpeg, Linux apt install ffmpeg).
2. Elija la forma del trabajo
| El usuario quiere | Haga esto |
|---|---|
| Un texto/título animado | render <estilo> --text "…" |
| Una animación de mapa/ruta | render map-route --set 'route=["Estambul","Konya"]' |
| Su imagen dibujada como un grabado | render image --image foto.jpg --look engrave --grade sepia --film 0.6 |
| Movimientos de cámara en su clip | render clip --clip video.mp4 --camera handheld --set speed='"ramp-mid"' |
| Una superposición transparente para su editor (rótulo inferior, subtítulos, CTA) | render lower-third --text "Nombre / Rol" --alpha --out nombre.mov |
| Un reel / documental / avance / introducción de varias escenas | init reel.json o comenzar desde una plantilla, luego editar (sección 4) |
Plantillas: node engine/cli.mjs templates las lista todas con una descripción de una línea.
Copie una junto a los activos del usuario (cp "$RM/templates/<nombre>.json" .), edite textos/rutas, renderícela.
3. Flujo de trabajo (siempre)
- Decida el/los estilo(s), texto, formato (por defecto 9:16 1080×1920), cámara, gradación.
- Primero verifique fotogramas fijos — son baratos y detectan problemas de diseño:
node "$RM/engine/cli.mjs" still <estilo|comp.json> --at 2.5 --size 540 --out "$TMP/check.png"→ abra el PNG y mírelo. Verifique 2–3 momentos (inicio, mitad, final de cada escena). Lea las líneas dewarning/error: nombran errores tipográficos y sugieren la clave correcta. - Renderice:
node engine/cli.mjs render … --out salida.mp4 - Verifique:
ffprobe -v error -show_entries format=duration -of csv=p=0 salida.mp4y capture uno o dos fotogramas. - Entregue el archivo con una línea de contexto.
Reglas prácticas
- El texto corto funciona mejor: 1–6 palabras por línea, máximo ~4 líneas. Use
" / "o\npara saltos de línea. - El uso de mayúsculas/minúsculas para el turco es automático cuando el texto contiene ğ/ş/ı/İ; en caso contrario, pase
--lang trpara texto turco (i → İ). - Los renders consumen mucha CPU: ~0.2–0.5 s por fotograma en 1080p. Previsualice con
--size 540y haga el render final a 1080. - Nunca descargue imágenes/clips de la web sin el consentimiento del usuario; use sus archivos.
- Superposiciones transparentes:
--alpha --out archivo.mov(ProRes 4444) o.webm. - Música:
--audio cancion.mp3y--bpm Npara quebeat-cut,lyric-videoy la cámarabeat-punchsigan el ritmo.
4. JSON de composición
{
"format": "9:16",
"lang": "tr",
"bpm": 96,
"audio": "cancion.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": ["Estambul", "Capadocia"], "duration": 6, "camera": "drift",
"transition": { "type": "whip", "duration": 0.45, "dir": "left" } },
{ "clip": "playa.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": "Nos vemos / pronto", "duration": 3 }
],
"overlays": [ { "style": "captions", "text": "…", "from": 0, "to": 5 } ]
}
- Tipos de escena:
style(cualquier id de estilo + sus opciones),image(rutaimage, olayers: [{src, depth}]para paralaje 2.5D),clip(clip,in,speed: número |ramp-in|ramp-out|ramp-mid),color. - Las rutas son relativas al archivo JSON.
transitionse sitúa en la escena que abandona. La siguiente escena comienzadurationsegundos antes de que termine esta.overlay= un estilo dibujado sobre esa escena (se mueve con su cámara).overlays= fijo sobre todo, sin gradación.- Cámara: nombre predefinido o
{ "preset": "drift", "amount": 0.6, "shake": 0.5, "keys": [{ "at": 0, "zoom": 1 }, { "at": 1, "zoom": 1.3, "ease": "outExpo" }] }.
5. Catálogo
Cámaras — 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. El movimiento de la cámara se desenfoca automáticamente.
Transiciones — cut, fade, flash, dip, whip, zoom, spin, glitch, ink, burn, liquid, iris, wipe, blinds, pixelate, leak, cube, ripple, doors, stretch, luma.
Looks (imágenes/clips) — engrave (la tinta dibuja → tramado → lavado sepia), sketch, oldphoto, duotone, halftone, posterize, noir. Opciones: { "type": "engrave", "reveal": 3, "delay": 0.2, "paper": "#ece0c4", "ink": "#33210f" }.
Gradaciones — none, teal-orange, kodak, fuji, sepia, noir, bleach, cyber, sunset, matte (+ gradeAmount 0–1).
Estilos — ejecute node engine/cli.mjs list para la lista en vivo. Las opciones de cada estilo están documentadas al principio de styles/<id>/style.js (defaults + options).
| Estilo | Qué hace | Opciones clave |
|---|---|---|
| map-route | Vuelo de ruta en globo / mapa plano / provincias de Turquía, pines + etiquetas | route, mode globe·flat·turkey·auto, theme dark·atlas·light, icon, highlight |
| history-title | Contador de años dorado + título de capítulo | text "1453 / Título / Subtítulo", from |
| parchment-letter | Pergamino quemado, escritura a mano + pluma + sello de lacre | place, signature, seal |
| murmuration | Banda de estorninos se pliega en las palabras | birds, colores del cielo |
| led-marquee | Carteles LED de tienda/minibús "kayan yazı" | un cartel por línea, colors |
| receipt | Impresora térmica imprime el mensaje, se rasga | header, items, total, date |
| ink-bleed | Gotas de tinta se extienden en las letras | ink, paper |
| halftone-press | Impresión risográfica a dos colores | inkA, inkB, dot |
| signal-tune | TV antigua: nieve → carta de ajuste → al aire | channel, station |
| inflate | Letras cromadas Y2K inflables | chrome, face |
| orbit-ring | Anillos de texto alrededor de un planeta | un anillo por línea |
| beat-cut | Una palabra sellada por pulso, póster suizo | bpm, offset |
| lyric-video | Las letras se iluminan palabra por palabra al ritmo | bpm, times, credit |
| captions | Subtítulos de reel, palabra activa en una píldora (use --alpha) | times, maxWords, pill, position |
| split-flap | Panel de salidas que gira (tambor turco) | title, cols |
| neon-sign | Tubos de neón sobre ladrillo, uno defectuoso | colors, broken |
| odometer | Dígitos rodantes cuentan hasta un número | text "10000 seguidores", prefix, suffix |
| pixel-quest | Pantalla de título de 8 bits | pixel, subtitle |
| vhs-memory | Aspecto de cinta de vídeo casera | date, clock |
| Tipo cinético | ||
| word-stack | Póster justificado apilado, cada línea aparece a ancho completo | accent, beat, kicker |
| typewriter | Escribe tecla por tecla con un cursor parpadeante | theme paper·terminal, speed, prompt |
| scramble | Glifos aleatorios se decodifican en el texto | font mono·display, resolve, hud |
| ticker-rows | Filas gigantes se desplazan en direcciones alternas | rows, tilt, speed, accent |
| highlight-quote | Cita aparece, un marcador resalta las palabras clave | author, highlight (palabras), marker |
| glitch-title | División RGB + datamosh se asientan en un título limpio | subtitle, colors, every |
| 3D | ||
| extrude-3d | Letras extruidas y robustas giran y se posan | face, side, bg, depth |
| cube-spin | Cubo gira cara a cara, una línea por cara | colors, ink, floor |
| text-tunnel | Vuele a través de anillos de texto hasta el título | línea 1 = título, rings, ring, colors |
| retro-grid | Cuadrícula synthwave, sol rayado, título cromado | línea 1 cromada, resto script, sky, sun, speed |
| particle-sphere | Esfera de partículas se transforma en las palabras | count, morphAt, colors |
| card-carousel | Anillo 3D de tarjetas aterriza en la última línea | images (archivos locales), turns, colors |
| Social y emisión | ||
| countdown | 3·2·1 con barrido de anillo, luego el texto | from, tick, accent |
| lower-third | Cintillo de nombre para noticias/YouTube (use --alpha) | línea 1 nombre, línea 2 rol, theme solid·glass·minimal, position |
| chat-story | Chat de mensajería con puntos de escritura | un mensaje por línea, > = yo, name, theme |
| bar-chart | Carrera de gráfico de barras, valores cuentan hacia arriba | items: [["A",10],…], unit, note, source |
| cta-follow | Cursor hace clic en Seguir, check + confeti | línea 1 handle, línea 2 botón, línea 3 subtítulo, done |
Las opciones de estilo se pasan con --set clave=valor (valores JSON: --set 'route=["A","B"]') o como claves del objeto de escena.
6. Solución de problemas
unknown place "X"(map-route): use"lat,lon"o{ "name": "X", "lat": 0, "lon": 0 }.- Texto recortado por un movimiento de cámara: reduzca el
amountde la cámara o usedrift/float. - Renders lentos:
--size 540para borradores. Evite--motion-blurpor encima de 4 a menos que el usuario quiera la máxima calidad. - Salida blanca/vacía: ejecute
stilly lea el error;doctorverifica WebGL2. - Windows PowerShell / cmd distorsionan
--set 'route=["A","B"]': escriba las opciones en un archivo y use--params opts.json, o use un JSON de composición. - Texto en inglés que contiene un nombre turco (ı, ş…) recibe mayúsculas/minúsculas turcas automáticamente; pase
--lang enpara detenerlo.