Que fait rudywizz-motion ?
Un moteur de rendu déterministe : chaque image est calculée (Chromium headless + WebGL2) et envoyée à ffmpeg, ainsi la même entrée produit toujours la même vidéo. Ce dossier est autonome :
engine/ cli.mjs (point d'entrée), host.js, timeline.js, camera.js, gl/ (shaders), data/ (cartes), fonts/
styles/ un dossier par style (style.js)
templates/ compositions prêtes à l'emploi (JSON)
assets/demo/ illustrations originales de démo (CC0)
1. Configuration unique (à vérifier avant le premier rendu)
RM="${CLAUDE_SKILL_DIR}" # le dossier qui contient ce 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 dossier temporaire que bash et Node reconnaissent (aussi sur Windows)
cd "$RM" && npm install --no-audit --no-fund # installe playwright (l'unique dépendance)
node engine/cli.mjs doctor # Node ✓ ffmpeg ✓ browser ✓ WebGL2 ✓ — chaque ✗ affiche sa solution
Exécutez les rendus depuis le dossier de l'utilisateur avec node "$RM/engine/cli.mjs" … pour que les chemins relatifs s'y résolvent.
Si la vérification du navigateur échoue : npx playwright install chromium (ou définissez RM_CHROME=/chemin/vers/chrome).
Si ffmpeg est manquant, dites à l'utilisateur comment l'installer (macOS brew install ffmpeg, Windows winget install ffmpeg, Linux apt install ffmpeg).
2. Choisissez la forme du travail
| L'utilisateur veut | Faites ceci |
|---|---|
| Un texte/titre animé | render <style> --text "…" |
| Une animation de carte / itinéraire | render map-route --set 'route=["İstanbul","Konya"]' |
| Son image dessinée comme une gravure | render image --image photo.jpg --look engrave --grade sepia --film 0.6 |
| Des mouvements de caméra sur son clip | render clip --clip in.mp4 --camera handheld --set speed='"ramp-mid"' |
| Un overlay transparent pour son éditeur (bandeau inférieur, sous-titres, CTA) | render lower-third --text "Nom / Rôle" --alpha --out nom.mov |
| Un reel / doc / teaser / intro multi-scène | init reel.json ou partez d'un template, puis éditez (section 4) |
Templates : node engine/cli.mjs templates les liste tous avec une description d'une ligne.
Copiez-en un à côté des ressources de l'utilisateur (cp "$RM/templates/<nom>.json" .), éditez textes/chemins, puis faites le rendu.
3. Flux de travail (toujours)
- Décidez du/des style(s), du texte, du format (par défaut 9:16 1080×1920), de la caméra, de l'étalonnage.
- Vérifiez d'abord avec des images fixes — peu coûteux et cela détecte les problèmes de mise en page :
node "$RM/engine/cli.mjs" still <style|comp.json> --at 2.5 --size 540 --out "$TMP/check.png"→ ouvrez le PNG et regardez-le. Vérifiez 2–3 moments (début, milieu, fin de chaque scène). Lisez les ligneswarning/error: elles nomment les fautes de frappe et suggèrent la bonne clé. - Rendu :
node engine/cli.mjs render … --out out.mp4 - Vérifiez :
ffprobe -v error -show_entries format=duration -of csv=p=0 out.mp4et extrayez une ou deux images. - Livrez le fichier avec une ligne de contexte.
Règles empiriques
- Le texte court gagne : 1–6 mots par ligne, max ~4 lignes. Utilisez
" / "ou\npour les sauts de ligne. - La casse turque est automatique lorsque le texte contient ğ/ş/ı/İ ; sinon passez
--lang trpour du texte turc (i → İ). - Les rendus sont gourmands en CPU : ~0,2–0,5 s par image 1080p. Prévisualisez avec
--size 540et faites le rendu final en 1080. - Ne téléchargez jamais d'images/clips depuis le web sans l'accord de l'utilisateur ; utilisez ses fichiers.
- Overlays transparents :
--alpha --out fichier.mov(ProRes 4444) ou.webm. - Musique :
--audio chanson.mp3et--bpm Npour quebeat-cut,lyric-videoet la camérabeat-punchsoient synchronisés.
4. JSON de composition
{
"format": "9:16",
"lang": "tr",
"bpm": 96,
"audio": "song.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": "beach.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": "portrait.jpg", "look": { "type": "engrave", "reveal": 3 }, "duration": 4, "camera": "push-in" },
{ "style": "neon-sign", "text": "À bientôt / soon", "duration": 3 }
],
"overlays": [ { "style": "captions", "text": "…", "from": 0, "to": 5 } ]
}
- Types de scènes :
style(n'importe quel id de style + ses options),image(cheminimage, oulayers: [{src, depth}]pour un effet de parallaxe 2.5D),clip(clip,in,speed: nombre |ramp-in|ramp-out|ramp-mid),color. - Les chemins sont relatifs au fichier JSON.
transitionse trouve sur la scène qu'elle quitte. La scène suivante commencedurationsecondes avant la fin de celle-ci.overlay= un style dessiné par-dessus cette scène (se déplace avec sa caméra).overlays= fixe par-dessus tout, non étalonné.- Caméra : nom d'un préréglage ou
{ "preset": "drift", "amount": 0.6, "shake": 0.5, "keys": [{ "at": 0, "zoom": 1 }, { "at": 1, "zoom": 1.3, "ease": "outExpo" }] }.
5. Catalogue
Caméras — 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. Le mouvement de caméra est automatiquement flouté de mouvement.
Transitions — cut, fade, flash, dip, whip, zoom, spin, glitch, ink, burn, liquid, iris, wipe, blinds, pixelate, leak, cube, ripple, doors, stretch, luma.
Looks (images/clips) — engrave (l'encre se dessine → hachures → lavis sépia), sketch, oldphoto, duotone, halftone, posterize, noir. Options : { "type": "engrave", "reveal": 3, "delay": 0.2, "paper": "#ece0c4", "ink": "#33210f" }.
Étalonnages (grades) — none, teal-orange, kodak, fuji, sepia, noir, bleach, cyber, sunset, matte (+ gradeAmount 0–1).
Styles — exécutez node engine/cli.mjs list pour la liste vivante. Les options de chaque style sont documentées en haut de styles/<id>/style.js (defaults + options).
| Style | Ce qu'il fait | Options clés |
|---|---|---|
| map-route | Vol d'itinéraire sur globe / carte plate / provinces turques, épingles + étiquettes | route, mode globe·flat·turkey·auto, theme dark·atlas·light, icon, highlight |
| history-title | Compteur d'années doré + titre de chapitre | texte "1453 / Titre / Sous-titre", from |
| parchment-letter | Parchemin brûlé, écriture manuscrite + plume + sceau de cire | place, signature, seal |
| murmuration | Nuée d'étourneaux se plie en mots | birds, couleurs du ciel |
| led-marquee | Panneaux LED "kayan yazı" de boutique/minibus | un panneau par ligne, colors |
| receipt | Imprimante thermique imprime le message, se détache | header, items, total, date |
| ink-bleed | Des gouttes d'encre s'étalent en lettres | ink, paper |
| halftone-press | Impression risographe deux couleurs | inkA, inkB, dot |
| signal-tune | Vieille télé : neige → mire → à l'antenne | channel, station |
| inflate | Lettres chromées gonflables Y2K | chrome, face |
| orbit-ring | Anneaux de texte autour d'une planète | un anneau par ligne |
| beat-cut | Un mot tamponné par temps, affiche suisse | bpm, offset |
| lyric-video | Paroles s'allument mot par mot sur le temps | bpm, times, credit |
| captions | Sous-titres de reel, mot actif sur un pilulier (utilisez --alpha) | times, maxWords, pill, position |
| split-flap | Tableau de départs à volets (drum turc) | title, cols |
| neon-sign | Tubes néon sur brique, un défectueux | colors, broken |
| odometer | Chiffres déroulants qui comptent jusqu'à un nombre | texte "10000 abonnés", prefix, suffix |
| pixel-quest | Écran titre 8-bit | pixel, subtitle |
| vhs-memory | Aspect bande vidéo amateur | date, clock |
| Typographie cinétique | ||
| word-stack | Pile justifiée façon affiche, chaque ligne claque en pleine largeur | accent, beat, kicker |
| typewriter | Tape touche par touche avec curseur clignotant | theme paper·terminal, speed, prompt |
| scramble | Glyphes aléatoires se décodent en texte | font mono·display, resolve, hud |
| ticker-rows | Lignes géantes défilent en directions alternées | rows, tilt, speed, accent |
| highlight-quote | Citation apparaît, un marqueur souligne les mots clés | author, highlight (mots), marker |
| glitch-title | RGB split + datamosh se stabilise en titre net | subtitle, colors, every |
| 3D | ||
| extrude-3d | Lettres extrudées massives basculent et tournent | face, side, bg, depth |
| cube-spin | Cube tourne face par face, une ligne par face | colors, ink, floor |
| text-tunnel | Vol à travers des anneaux de texte jusqu'au titre | ligne 1 = titre, rings, ring, colors |
| retro-grid | Grille synthwave, soleil rayé, titre chromé | ligne 1 chromée, reste script, sky, sun, speed |
| particle-sphere | Sphère de particules se transforme en mots | count, morphAt, colors |
| card-carousel | Anneau 3D de cartes atterrit sur la dernière ligne | images (fichiers locaux), turns, colors |
| Social & broadcast | ||
| countdown | 3·2·1 avec anneaux qui balayent, puis le texte | from, tick, accent |
| lower-third | Bandeau d'identification news/YouTube (utilisez --alpha) | ligne 1 nom, ligne 2 rôle, theme solid·glass·minimal, position |
| chat-story | Conversation de messagerie avec points de saisie | un message par ligne, > = moi, name, theme |
| bar-chart | Course de graphique à barres, valeurs qui comptent | items: [["A",10],…], unit, note, source |
| cta-follow | Curseur clique sur Suivre, coche + confettis | ligne 1 pseudo, ligne 2 bouton, ligne 3 sous-titre, done |
Les options de style se passent avec --set clé=valeur (valeurs JSON : --set 'route=["A","B"]') ou comme clés de l'objet scène.
6. Dépannage
unknown place "X"(map-route) : utilisez"lat,lon"ou{ "name": "X", "lat": 0, "lon": 0 }.- Texte coupé par un mouvement de caméra : diminuez l'
amountde la caméra ou utilisezdrift/float. - Rendus lents :
--size 540pour les ébauches. Évitez--motion-blurau-dessus de 4 sauf si l'utilisateur veut la meilleure qualité. - Sortie blanche/vide : exécutez
stillet lisez l'erreur ;doctorvérifie WebGL2. - Windows PowerShell / cmd déforme
--set 'route=["A","B"]': écrivez les options dans un fichier et utilisez--params opts.json, ou un JSON de composition. - Un texte anglais qui contient un nom turc (ı, ş…) obtient automatiquement la casse turque ; passez
--lang enpour l'arrêter.