Communitygithub.com

Apollonny/stickman-explainer

Produit des vidéos explicatives animées en format vertical (9:16) avec des personnages en bâtonnets, type Reels/TikTok/Shorts, à partir d'un storyboard JSON et d'un rendu Python.

Qu'est-ce que stickman-explainer ?

Ce skill transforme un script narratif court en vidéo MP4 au format 1080×1920 (9:16) en utilisant un moteur de rendu Python piloté par un storyboard JSON. Il génère des animations de type « stickman » (personnages en bâtonnets) avec un style dessiné à l'encre noire sur fond de papier crème, un accent rouge pour les mots-clés, et un motif de soleil optionnel. Idéal pour créer des vidéos explicatives, historiques ou anecdotiques pour Instagram Reels, TikTok ou YouTube Shorts, le skill propose des transitions (fondu, wipe, pop), un effet de « line-boil » à 8 FPS, et un support de synchronisation mot-par-mot (karaoké) pour les sous-titres lorsqu'un fichier audio est fourni. Il vérifie rigoureusement la syntaxe du storyboard avant le rendu et offre des options pour une prévisualisation rapide (stills) et une version brouillon accélérée. Le skill est conçu pour être utilisé avec des agents de codage IA (Claude Code, Cursor, Codex) pour automatiser la production de ces vidéos à partir d'un simple script ou d'une commande comme « fais une vidéo comme ce reel ».

Compatible avec✓Claude Code✓Codex CLI~Cursor✓Antigravity✓OpenCode
npx skills add https://github.com/Apollonny/stickman-explainer/tree/main/stickman-explainer

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait stickman-explainer ?

Transforme un script court en un fichier MP4 1080×1920 terminé. Vous écrivez un storyboard JSON ; scripts/render.py dessine chaque image (traits d'encre tremblés, « line-boil » à 8 fps, révélations fondu/wipe/pop) et encode avec ffmpeg.

assets/example_storyboard.json n'est qu'un exemple de syntaxe (3 scènes) ; ne pas copier sa mise en page ou ses accessoires de personnages comme modèle.

Valeurs par défaut du style visuel

  • Utilisez un canevas 9:16 (1080×1920, 30 fps). Gardez chaque scène pour une seule idée, généralement 2,5–4 secondes, avec des sous-titres courts dans les zones de sécurité de la plateforme.
  • Utilisez un papier chaud (#f3ebdd), une encre foncée (#2b2723) et un accent rouge brique sémantique (#b8372d). L'or soleil (#d89d48) est optionnel uniquement pour le motif du soleil. Gardez le reste plat : pas de dégradés, d'ombres ni d'effets 3D.
  • Dessinez des personnages simples à l'encre noire avec des visages clairs et beaucoup d'espace négatif. N'ajoutez pas de casques, couronnes, capes, vêtements rouges ou autres accessoires sauf si l'histoire ou l'utilisateur le demande explicitement. Ne déduisez pas de costumes d'un nom historique.
  • Gardez les scènes lisibles : au maximum 2 personnages et 5 petites icônes. Rendez le sujet principal dominant ; évitez la superposition des sous-titres et des accessoires. Utilisez au maximum 2 lignes de sous-titres.
  • Rendez les accessoires complexes reconnaissables. Dessinez un nœud avec des boucles distinctes qui se croisent, un centre serré et des extrémités de corde visibles. Donnez à une épée une poignée claire, une garde et une lame pointue. Après une coupe, laissez un espace visible entre les deux extrémités de la corde.
  • Lorsque les durées de narration sont disponibles, faites suivre l'emphase rouge du sous-titre au mot actuellement parlé tout au long de la narration. Utilisez un intervalle karaoke pour chaque mot du sous-titre séparé par des espaces ; les mots inactifs restent dans la couleur de texte normale.
  • Préférez des dispositions asymétriques et laissez délibérément de l'espace négatif. Les lignes de sol, soleils, cartes de titre, bulles de pensée et autres motifs sont optionnels ; choisissez-les uniquement lorsqu'ils soutiennent la scène.

Flux de travail

  1. Script → scènes. Découpez l'histoire en scènes d'une phrase (≤ 6 mots de sous-titre, 2,5–4 s chacune). Motif : carte de titre → accroche/conflit → révélation concrète. Chaque scène ajoute exactement une nouvelle information. Lorsqu'une narration est fournie, alignez les limites des scènes sur les phrases parlées.
  2. Choisissez un visuel pour chaque phrase. Une métaphore par scène : personnage + accessoire, bulle de pensée ou une rangée d'icônes (X = « n'a pas »). Gardez ≤ 2 personnages et ≤ 5 icônes.
  3. Écrivez le storyboard (schéma ci-dessous). Avec des durées de narration mot par mot, ajoutez un intervalle karaoke pour chaque mot du sous-titre séparé par des espaces afin que l'accent rouge suive le mot prononcé. Utilisez **mot** uniquement pour un surlignage statique lorsque la durée des mots n'est pas disponible ; ne combinez pas le balisage statique avec karaoke.
  4. Vérifiez d'abord les images fixes (rapide, ~2 s/scène) : python scripts/render.py story.json --stills out/stills → ouvrez chaque scene_NN.png, corrigez les superpositions/placement, répétez.
  5. Vidéo brouillon : python scripts/render.py story.json out/draft.mp4 --draft (pas de sur-échantillonnage, 12 fps).
  6. Final : python scripts/render.py story.json out/final.mp4 [--audio voiceover.mp3]. Les durées des scènes doivent correspondre aux longueurs des phrases de la voix off ; mesurez l'audio avec ffprobe et définissez duration en conséquence. Les intervalles des mots sont en secondes depuis le début de leur scène et doivent provenir de l'alignement de la narration ou d'une écoute attentive. Vérifiez que chaque mot rouge apparaît avec son audio parlé, pas avant ni après.

Messages d'erreur et validation

render.py valide le storyboard avant de le dessiner : il rejette type/pose/face/kind/font inconnus, champ obligatoire manquant, id répété dans la même scène, duration <= 0, chemin lines à un seul point, résolution impaire (non paire) et id de carry inexistant avec un message clair au lieu d’un traceback. Il émet un avertissement pour les éléments qui ne seront jamais visibles (at après la fin de la scène). Si le fichier audio est plus court que la vidéo, la fin est remplie de silence ; s'il est plus long, il est coupé ; la durée de la vidéo ne change jamais.

Schéma du storyboard

{"meta": {"width":1080,"height":1920,"fps":30,"boil_fps":8,"transition":0.18,
          "palette":{"accent":"#b8372d"}, "audio":null, "font_dirs":[]},
 "scenes":[{"duration":3.4, "caption":"C'était **Alexandre** le Grand.",
            "caption_at":0.5, "caption_y":null, "elements":[ ... ]}]}

Pour une emphase mot-par-mot suivant la parole, fournissez un tableau karaoke avec un objet { "start": secondes, "end": secondes } par mot séparé par des espaces dans caption. Les temps sont locaux à la scène ; l'accent rouge bascule à chaque intervalle. Le sous-titre ne doit pas contenir de balisage **...** lorsque karaoke est présent.

{"duration":2.8, "caption":"Il coupa le nœud d'un seul geste.", "caption_at":0.35,
 "karaoke":[{"start":0.35,"end":0.76},{"start":0.76,"end":1.02},
            {"start":1.02,"end":1.53},{"start":1.53,"end":2.15}],
 "elements":[ ... ]}

Chaque élément : type, id optionnel (pour carry), at (s, temps d'apparition), dur (s, durée de révélation), anim = fade | wipe | rise | pop, until/out_dur (s, fondu de sortie). Les positions x,x2,y,ground ≤ 2 sont lues comme des fractions de la largeur/hauteur, sinon en pixels. Les tailles sont toujours en pixels.

typechamps clés
groundy (obligatoire) ; x, x2 optionnels, si absents ~%2–%98 du canevas — ligne de base tremblée
sunx,y,r,rays
texttext (balisage **accent**), x,y,size,font = sans/sans_bold/sans_light/serif, tracking, caps, color, max_w, max_lines (défaut 3), rules (double ligne pour carte de titre ; largeur et espacement automatiques selon le texte)
figurex,ground,h,head_r, pose = stand/arms_open/point/wave/think/shrug/sit, dir (±1), face = neutral/smile/sad/surprised/angry, accessory optionnel = helmet/crown/hat/glasses, cape optionnel, look
propkind = barrel/bowl/bucket/house/book/box/triangle/coins/tree, x,y (coin supérieur gauche), w,h, cross (X accent), flip
thoughtx,y,w,h, tail_to [px,py] (position de la tête), inner : liste d'éléments en px locaux dans la bulle
linespaths (liste de listes de points, px locaux), closed, smooth, color, width — échappatoire pour toute forme personnalisée

Continuité entre scènes (carry)

Pour transporter un élément d'une scène à la suivante, donnez-lui un id, puis appelez-le dans la scène suivante avec carry. L'élément transporté commence avec la même vibration de ligne (même seed), il apparaît donc comme le « même dessin » même si la scène change ; la transition de nouvelle scène est par défaut une coupe (pas de fondu enchaîné).

"carry": [
  "ground",
  {"id": "sun",  "set": {"r": 122}},
  {"id": "alex", "set": {"x": 120, "face": "smile"}, "tween": {"at": 0.1, "dur": 0.9}},
  {"id": "diog", "until": 0.1, "out_dur": 0.5}
]

Les lignes sont exécutées dans l'ordre : "ground" est transporté tel quel · sun est transporté avec des champs modifiés (le changement est instantané au début de la scène) · alex change de champs et sa position glisse pendant la durée (tween) · diog est transporté mais disparaît en fondu pendant la scène.

  • "carry": "all" transporte tout ("carry_except": ["id", ...] exclut). Les sous-titres ne sont jamais transportés.
  • Un élément non transporté disparaît instantanément au début de la scène ; utilisez until/out_dur pour une disparition en douceur. Un élément qui disparaît avec until ne peut pas être transporté à la scène suivante.
  • tween n'anime que la position (x et y/ground) ; les changements de taille (r, h, w) et d'apparence (face, pose) sont appliqués instantanément au début de la scène.
  • Les éléments transportés sont dessinés sous les nouveaux éléments. Les id doivent être uniques entre les scènes pour les éléments transportés.
  • Un élément avec le même id utilise la même seed dans chaque scène ; pour un nouvel élément propre à une scène, ne donnez pas d'id.

Ajoutez de nouveaux accessoires/poses en étendant PROPS / hands dans render.py ; conservez le même style d'encre (utilisez stroke(), jamais de lignes simples).

Disposition : décidez à nouveau pour chaque vidéo

Pas de coordonnées/modèles fixes. Comme le sujet de chaque vidéo est différent, dérivez la disposition du contenu de la scène :

  • Choisissez d'abord l'idée visuelle unique de cette phrase (comparaison, liste, rêve, voyage, nombre…), puis construisez la disposition qui lui convient. La disposition peut changer entre les scènes d'une même vidéo.
  • Faites de la place pour l'élément important : le sujet principal doit être le plus grand/le plus visible ; les éléments secondaires restent petits. Laissez délibérément un espace vide (espace négatif).
  • La taille, la position et le nombre varient selon le contenu (1 personnage ou 2 ; rangée d'icônes ou un seul grand objet ; carte/chronologie). Si nécessaire, utilisez lines pour dessiner une forme personnalisée.
  • N'ajoutez pas automatiquement de costumes/coiffes aux personnages historiques. Les figures sont dessinées sans accessoires par défaut ; casque, couronne, chapeau ou cape ne sont ajoutés que si le récit ou l'utilisateur le demande explicitement. N'étendez pas la couleur d'accent comme décoration sur les vêtements du personnage.
  • Pour les scènes de nœud et de coupe, rendez l'objet lisible : dessinez la corde avec plusieurs boucles distinctes qui se croisent, montrez le nœud serré au centre et distinguez les extrémités. Pour l'épée, la poignée, la garde et la lame pointue doivent être visibles. Après la coupe, laissez les deux extrémités de la corde coupée espacées et clairement visibles ; l'épée et le nœud ne doivent pas être masqués par les sous-titres. Dessinez les formes spéciales de corde/épée avec lines.
  • Les motifs comme la ligne de sol, le soleil, la carte de titre sont optionnels ; ne les utilisez pas s'ils ne correspondent pas au sujet (par ex. intérieur, nuit, concept abstrait).
  • Placez le sous-titre lisiblement et loin de l'interface de la plateforme ; en cas de conflit, ajustez avec caption_y. Vérifiez visuellement les superpositions et les débordements sur les images fixes, ne vous fiez pas aux chiffres.
  • Les coordonnées de dessin sont données en pixels (ou en proportion 0–2) sur le canevas 1080×1920 ; planifiez les valeurs à zéro pour chaque scène.

Pièges

  • Visualisez toujours les images fixes avant l'encodage ; les éléments superposés et les rayons de soleil coupés sont les défauts courants. Utilisez --draft pour le brouillon, le rendu complet pour les détails : les images inchangées ne sont pas redessinées, une vidéo de 10 s prend environ 20 s en pleine qualité.
  • Le sous-titre passe à la ligne jusqu'à 86 % de largeur (3 lignes max), mais si un mot ne tient pas ou dépasse 3 lignes, la taille est réduite. Scindez une phrase de plus de 2 lignes en deux scènes. La position par défaut du sous-titre n'est qu'une sauvegarde ; si nécessaire, fournissez caption_y dans la scène.
  • Polices : installez Poppins et Playfair Display (ou Lora), ou fournissez --font-dir. Si aucune police TrueType n'est trouvée, le moteur de rendu émet un avertissement et les caractères turcs (İ ş ğ â) peuvent manquer ; vérifiez sur les images fixes. Les dossiers de polices Linux, macOS et Windows sont scannés.
  • Gardez la couleur d'accent sémantique (sujet, mot-clé, négation). N'ajoutez pas d'autres couleurs.
  • Lorsque karaoke est présent, l'accent rouge du sous-titre suit le mot par mot de la narration en utilisant les intervalles fournis. Ne laissez pas un mot-clé rouge fixe à l'écran ; rendez les mots inactifs dans la couleur de texte du sous-titre.

Skills associés