Communitygithub.com

orange9angel/dula-flat-cel

Créez des courts métrages d'animation en aplat avec un modèle d'image et des scripts, de l'histoire aux designs des personnages, dessins et variantes de bouche jusqu'à une vidéo finale sonorisée. Nécessite seulement Python et ffmpeg.

Qu'est-ce que dula-flat-cel ?

Ce skill permet de produire des courts métrages d'anision en aplat (flat-color) dans un style cartoon TV, en utilisant un modèle d'image (comme DALL-E, Stable Diffusion, etc.) et des scripts Python. L'animation repose sur un faible nombre de dessins (3-4 images par plan) et des permutations de bouche, ce qui garantit une cohérence que les modèles vidéo peinent à atteindre. Idéal pour des films dialogués, des cycles de marche, ou des personnages récurrents, il évite les problèmes de bouche désynchronisée et de scintillement lors des changements de dessin. Le workflow couvre l'écriture du scénario, la création des designs, le découpage en plans, la génération des variantes de bouche, l'ajout de sons (voix générées ou fichiers audio), le rendu final et une vérification de qualité automatisée. Compatible avec tout environnement Python et ffmpeg, il s'utilise aussi bien en local que sur des plateformes d'agents comme Codex ou Cursor.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/orange9angel/dula-craft/tree/HEAD/skills/dula-flat-cel

Demander à votre IA préférée

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

Documentation

Animation en aplat

Un dessin dure 3 à 4 images, et le mouvement vient des changements de dessin et des formes de bouche. Pour les designs cartoon TV simples, c'est la méthode qui donne les résultats les plus cohérents avec les modèles d'image. Elle ne nécessite ni 3D ni modèle vidéo.

Les scripts se trouvent dans le dossier scripts/ de ce skill, avec des chemins relatifs à ce SKILL.md. Ci-dessous, $S désigne ce dossier. Sauf pour new_project.py, exécutez-les depuis le dossier du film. En cas de problème d'environnement, utilisez dula-start.

Parlez à la personne dans sa propre langue.

Flux de travail

python $S/new_project.py mon_film && cd mon_film

1. Histoire et plans

Rédigez story.md, puis config/film.json (voir la référence film.json). Limitez un premier film à 20–30 secondes ; une réplique dure environ 2–3 secondes, donc 15 secondes contiennent 3–5 répliques. Utilisez uniquement des personnages originaux.

Pour chaque réplique, réfléchissez à qui parle, à qui, et qui est montré par la caméra. Les blagues ne doivent pas reposer sur des mots que le public ne comprendrait pas. La cause et l'effet ont besoin de dessins (entre → attrape → l'objet s'envole). Ne les escamotez pas avec un cut.

2. Designs des personnages (l'étape la plus importante)

Placez chaque personnage dans config/anchors.tsv (nom<TAB>apparence), puis exécutez :

python $S/paint.py anchors config/anchors.tsv

Ouvrez et regardez chaque image vous-même. Certains visionneurs affichent une zone transparente comme une lueur colorée sur fond noir, ce qui ressemble à un découpage raté. En cas de doute, vérifiez build/check_alpha.png de l'étape 3. Montrez ensuite les designs à la personne et obtenez son approbation avant de continuer. Tous les dessins ultérieurs suivent ces designs, donc une erreur ici coûte le plus à corriger. Corrigez les proportions en mots, par exemple "tête un tiers de la hauteur totale, visage rond, petits yeux ronds noirs, salopettes rouges".

3. Décors et dessins

Remplissez config/plates.tsv (nom<TAB>description) et config/cels.tsv (dessin<TAB>personnage<TAB>pose). Commencez les noms de dessins par le nom du personnage, comme hero_run_a.

python $S/paint.py plates config/plates.tsv
python $S/paint.py cels config/cels.tsv
python $S/prep_cels.py --bases-only    # Vérifiez les découpages dans build/check_alpha.png avant de peindre les bouches

Les images prennent 1 à 3 minutes chacune, et paint.py signale la progression. Si votre outil interrompt les longues commandes, exécutez-les en arrière-plan. Une réexécution ignore les images déjà faites. Pour refaire une image, utilisez --only <nom> --force.

Pour assurer la continuité des dessins et des lieux, ajoutez une colonne supplémentaire indiquant ce qu'il faut suivre :

hero_run_a	hero	Courant vers la droite, pied gauche en avant.
hero_run_b	hero	Courant vers la droite, pied droit en avant.	hero_run_a
meadow	Un pré sous des nuages de pluie gris.
meadow_sun	La pluie a cessé et le soleil perce les nuages.	meadow

Règles :

  • Dessinez un personnage par image. Le design du personnage est toujours la première référence. N'utilisez jamais une image rejetée comme référence.
  • Décidez d'abord dans quelle direction les personnages regardent. Les images générées une par une choisissent chacune une direction, donc deux personnes en conversation peuvent facilement se retrouver dos à dos. Spécifiez-le à l'avance et utilisez flip pour corriger les erreurs.
  • Chaque dessin d'un cycle d'action suit le précédent (la colonne supplémentaire ci-dessus), afin que la direction, l'échelle et la forme restent stables. Sans cela, un cycle saute.
  • Pour un changement d'heure de la journée, repeignez le décor en suivant la plaque d'origine. Multiplier une couleur ne peut pas masquer un ciel bleu.
  • Vérifiez les proportions d'un personnage dans chaque plan. Une description de pose comme "cou tendu vers le haut" peut donner un corps différent.

4. Bouches et clignements

Chaque dessin qui parle reçoit des éditions locales de la même image. Dans config/variants.tsv :

hero_stand_m1	hero_stand	Changer uniquement la bouche en demi-ouverte, petit ovale.
hero_stand_m2	hero_stand	Changer uniquement la bouche en grande ouverte.
hero_stand_blink	hero_stand	Fermer les deux yeux en simples lignes courbes. Ne rien changer d'autre.

Noms : <base>_m1 est demi-ouverte, <base>_m2 est grande ouverte. Avec seulement _m1, la bouche a deux états, ouvert et fermé, et cela fonctionne aussi. Le dessin de base lui-même doit avoir une bouche fermée. S'il est dessiné avec la bouche ouverte, créez une variante fermée et définissez les trois états avec talk dans film.json.

Chaque dessin d'un personnage qui parle a besoin de ses propres bouches, y compris chaque dessin d'un cycle de marche.

python $S/paint.py variants config/variants.tsv
python $S/prep_cels.py

prep_cels.py réduit les dessins à de vraies couleurs d'aplat et verrouille chaque variante sur sa base. Ensuite, ouvrez build/check_alpha.png et vérifiez les découpages sur magenta. Redessinez toute image avec un fond restant, des parties manquantes ou des yeux effacés. Si le script avertit d'une grande zone modifiée, le modèle a modifié le corps. Ajoutez une fenêtre x,y,w,h en colonne 4 de variants.tsv.

Les couleurs dérivent ? Vous pouvez ajouter config/palette.json ({"skin": [250, 220, 190]}), en utilisant des couleurs échantillonnées du design du personnage. Seules les couleurs proches s'y alignent, et prep_cels.py l'applique à nouveau après chaque modification.

5. Son

Choisissez une option :

  • Générez des voix avec dula-voice, en utilisant la propre clé de la personne.
  • Utilisez un fichier audio existant : placez-le dans audio/voice/<numéro de réplique>.wav, ou définissez file sur la réplique. mp3 et wav fonctionnent tous deux.
  • Faitez un brouillon muet : donnez à la réplique une valeur seconds.

Les bouches sont calculées à partir de cet audio, donc fixez les voix avant de faire le test.

Optionnel : ambience, bgm, sfx et songs. Utilisez uniquement du matériel dont la personne possède les droits. Ce projet ne génère pas de musique. Sans musique sous licence, laissez la partition de côté et laissez l'ambiance et les effets sonores porter le film.

6. Test

python $S/build_film.py
python $S/render.py --stills 1,3,5,8,12
python $S/render.py --range 0,20 -o output/pilot.mp4

build_film.py s'arrête avec une erreur si un personnage visible parle mais que sa bouche ne peut pas bouger – l'erreur la plus facile à manquer. Regardez chaque image fixe avant de montrer le test. N'attendez pas que tout le film soit terminé pour le montrer à quelqu'un.

Positionner un personnage au sol : estimez ground, faites un rendu d'image fixe, et ajustez. C'est plus rapide que de le calculer.

Ne laissez pas les plans immobiles. Sauf si un temps doit être statique, donnez à chaque plan une chose qui bouge : un panoramique sur le décor, un bob ou shake, un changement de dessin, ou une superposition comme la pluie. Terminez le film par fade_out sur le dernier plan.

7. Film complet et vérification finale

python $S/render.py
python $S/check_mouths.py

Confirmez chacun de ces points avant de remettre le travail, et dites clairement si vous n'avez pas pu :

  • Vous avez regardé une image réelle de chaque plan
  • check_mouths.py ne signale aucune bouche figée
  • Chaque personnage ressemble toujours à la même personne d'un plan à l'autre (le visage et les proportions importent plus que la couleur)
  • Les personnes en conversation se font face
  • Un dessin unique se déplaçant sur l'écran a un bob ou plusieurs dessins, sinon on a l'impression qu'il glisse
  • Vous avez écouté le résultat. Si vous ne pouvez pas écouter, dites que l'audio n'a pas été vérifié à l'oreille

Un exemple complet

examples/rainy-slide dans ce dépôt contient les prompts et la liste de plans d'un film fini de 15 secondes, et docs/tutorial.md l'explique. Trouvez-les sous ../../examples/rainy-slide et ../../docs/tutorial.md à partir de ce fichier. Utilisez-les comme modèle lorsque quelqu'un en demande un.

Rythme

Règles empiriques : les plans durent en moyenne 3 à 5 secondes, les personnages tiennent chaque dessin 3 à 4 images (environ 7 dessins par seconde), avec de fréquents gros plans et expressions exagérées. hold est le nombre d'images par dessin.

Problèmes courants

SymptômeCause et correctif
Les couleurs du corps scintillent lors des changements de boucheLa variante n'est pas passée par prep_cels.py
Une marche ou une course pulse en hauteur et largeurNe dimensionnez pas les dessins séparément. Un même acteur partage automatiquement une seule échelle. Ajoutez aussi align_head
Un accessoire prend la mauvaise couleurUne entrée de palette est trop proche. Supprimez-la ou abaissez SNAP
La bouche reste ouverte pendant le discoursLes bouches à deux états utilisent un seuil de 0,5. Vérifiez si l'audio est étouffé
Les mots silencieux restent fermésUn mot fort définit l'échelle de sa réplique. Ajoutez un _m2, ou abaissez mouth_open_at sur la réplique
La pluie ou le vent ne s'entendent pasL'ambiance est silencieuse par défaut. Donnez-lui un level_db, par exemple -35
Sifflement constantLe clip d'ambiance n'est que du bruit. Remplacez-le. Le gain est plafonné, donc il ne sera pas amplifié davantage
Codex indique que l'image de référence a été perdueLa génération d'image doit être sa première action. paint.py gère cela, donc exécutez-le à nouveau

Limites

Cette méthode n'est pas adaptée aux combats complexes, aux longues actions continues ou à la peinture réaliste.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés