Communitygithub.com

orange9angel/dula-flat-cel

Erstelle flächige, linienbasierte Animationskurzfilme mit einem Bildmodell und Skripten – von Story, Charakterdesigns, Zeichnungen und Mundvarianten bis zum fertigen Video mit Ton. Benötigt nur Python und ffmpeg.

Was ist dula-flat-cel?

Dieses Skill ermöglicht die Produktion von flächigen, linienbasierten Animationsfilmen im TV-Cartoon-Stil, indem es auf Bildgenerierungsmodelle und Python-Skripte setzt – ohne 3D- oder Videomodelle. Es eignet sich besonders für Dialogfilme mit limitierter Animation, bei denen ein Charakter konsistent über verschiedene Szenen hinweg dargestellt werden muss und Probleme wie asynchrone Mundbewegungen oder flackernde Zeichnungswechsel vermieden werden sollen. Der Workflow ist klar strukturiert: Zuerst werden Story und Shots definiert, dann Charakterdesigns mit einem Bildmodell erstellt, anschließend Hintergründe und Zeichnungen generiert, Mundvarianten und Lidschläge hinzugefügt, der Ton (Sprache, Ambience, Soundeffekte) integriert und schließlich der Film gerendert. Die Skripte liegen im `scripts/`-Ordner des Skills; `new_project.py` initialisiert ein Projekt, alle anderen Skripte werden aus dem Filmordner heraus ausgeführt. Das Skill ist als Werkzeug für Claude Code, Cursor und Codex konzipiert und legt großen Wert auf Qualitätskontrolle durch manuelle Überprüfung jedes Bildes und automatisierte Prüfungen wie `check_mouths.py`.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Flächige Animation

Eine Zeichnung hält 3–4 Frames, und die Performance entsteht durch das Austauschen von Zeichnungen und Mundformen. Für einfache TV-Cartoon-Designs ist dies der Weg, bei dem Bildmodelle am konsistentesten bleiben. Es benötigt weder 3D noch ein Videomodell.

Die Skripte befinden sich im scripts/-Ordner dieses Skills, mit Pfaden relativ zu dieser SKILL.md. Im Folgenden bedeutet $S diesen Ordner. Mit Ausnahme von new_project.py führe sie aus dem Filmordner aus. Bei Umgebungsproblemen verwende dula-start.

Sprich mit der Person in ihrer eigenen Sprache.

Arbeitsablauf

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

1. Geschichte und Shots

Schreibe story.md, dann config/film.json (siehe film.json-Referenz). Halte einen ersten Film auf 20–30 Sekunden, und eine gesprochene Zeile dauert etwa 2–3 Sekunden, also passen in 15 Sekunden 3–5 Zeilen. Verwende nur Originalcharaktere.

Denke bei jeder Zeile darüber nach, wer sie sagt, zu wem und wen die Kamera zeigt. Witze sollten nicht auf Wörtern beruhen, die das Publikum nicht versteht. Ursache und Wirkung benötigen ebenfalls Zeichnungen (rennt rein → greift → das Objekt fliegt weg). Überspringe es nicht mit einem Schnitt.

2. Charakterdesigns (der wichtigste Schritt)

Füge jeden Charakter in config/anchors.tsv ein (Name<TAB>Aussehen), dann führe aus:

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

Öffne und betrachte jedes Bild selbst. Manche Betrachter zeigen einen transparenten Bereich als farbiges Leuchten auf Schwarz, was wie ein fehlgeschlagener Ausschnitt aussieht. Im Zweifel überprüfe build/check_alpha.png aus Schritt 3. Zeige dann die Designs der Person und hole ihre Zustimmung ein, bevor du fortfährst. Jede spätere Zeichnung folgt diesen, daher kostet ein Fehler hier am meisten, um ihn zu beheben. Korrigiere die Proportionen in Worten, z. B. "Kopf ein Drittel der Gesamthöhe, rundes Gesicht, kleine schwarze Perlenaugen, rote Latzhose".

3. Hintergründe und Zeichnungen

Fülle config/plates.tsv aus (Name<TAB>Beschreibung) und config/cels.tsv (Zeichnung<TAB>Charakter<TAB>Pose). Beginne Zeichnungsnamen mit dem Charakternamen, wie held_rennen_a.

python $S/paint.py plates config/plates.tsv
python $S/paint.py cels config/cels.tsv
python $S/prep_cels.py --bases-only    # Überprüfe Ausschnitte in build/check_alpha.png, bevor du Münder malst

Bilder benötigen 1–3 Minuten pro Stück, und paint.py meldet den Fortschritt. Falls dein Tool lange Befehle abbricht, führe es im Hintergrund aus. Ein erneuter Durchlauf überspringt fertige Bilder. Um eines zu wiederholen, verwende --only <Name> --force.

Um Zeichnungen und Orte kontinuierlich zu halten, füge eine weitere Spalte hinzu, die angibt, was befolgt werden soll:

held_rennen_a  held  Nach rechts rennen, linkes Fuß vorne.
held_rennen_b  held  Nach rechts rennen, rechtes Fuß vorne.  held_rennen_a
wiese  Eine Wiese unter grauen Regenwolken.
wiese_sonne  Der Regen hat aufgehört und die Sonne bricht durch.  wiese

Regeln:

  • Zeichne ein Charakter pro Bild. Das Charakterdesign ist immer die erste Referenz. Verwende niemals ein abgelehntes Bild als Referenz.
  • Entscheide zuerst, in welche Richtung die Charaktere schauen. Da Bilder einzeln generiert werden und jede eine Richtung wählt, können zwei Personen in einem Gespräch leicht Rücken an Rücken enden. Gib es von Anfang an an und verwende flip, um Fehler zu korrigieren.
  • Jede Zeichnung in einem Aktionszyklus folgt der vorherigen (die zusätzliche Spalte oben), sodass Richtung, Größe und Form stabil bleiben. Ohne dies springt ein Zyklus.
  • Für einen Tageszeitwechsel übermale den Hintergrund neu, der der ursprünglichen Platte folgt. Eine Farbmultiplikation kann einen blauen Himmel nicht verstecken.
  • Überprüfe die Proportionen eines Charakters in jedem Shot. Eine Posenbeschreibung wie "Hals nach oben gestreckt" kann zu einem anderen Körper führen.

4. Münder und Lidschläge

Jede Zeichnung, die spricht, erhält lokale Bearbeitungen desselben Bildes. In config/variants.tsv:

held_stehen_m1  held_stehen  Ändere nur den Mund zu halb geöffnet, kleines Oval.
held_stehen_m2  held_stehen  Ändere nur den Mund zu weit geöffnet.
held_stehen_blink  held_stehen  Schließe beide Augen als einfache gebogene Linien. Ändere nichts anderes.

Namen: <Basis>_m1 ist halb geöffnet, und <Basis>_m2 ist weit geöffnet. Mit nur _m1 hat der Mund zwei Zustände, offen und geschlossen, und das funktioniert auch. Die Basiszeichnung selbst muss einen geschlossenen Mund haben. Wenn sie mit offenem Mund gezeichnet wurde, erstelle eine geschlossene Variante und setze alle drei Zustände mit talk in film.json.

Jede Zeichnung eines sprechenden Charakters benötigt ihre eigenen Münder, einschließlich jeder Zeichnung in einem Gehzyklus.

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

prep_cels.py drückt Zeichnungen in echte flächige Farbe und sperrt jede Variante an ihre Basis. Dann öffne build/check_alpha.png und überprüfe die Ausschnitte auf Magenta. Zeichne jedes Bild mit übriggebliebenem Hintergrund, fehlenden Teilen oder gelöschten Augen neu. Wenn eine Warnung über einen großen geänderten Bereich erscheint, hat das Modell den Körper bearbeitet. Füge ein Fenster x,y,w,h als Spalte 4 in variants.tsv hinzu.

Farben driften? Du kannst config/palette.json hinzufügen ({"skin": [250, 220, 190]}), unter Verwendung von Farben, die aus dem Charakterdesign entnommen wurden. Nur nahe Farben schnappen darauf ein, und prep_cels.py wendet es erneut an, nachdem du es geändert hast.

5. Ton

Wähle eine Option:

  • Generiere Stimmen mit dula-voice, unter Verwendung des eigenen Schlüssels der Person.
  • Verwende vorhandenes Audio: lege es unter audio/voice/<Zeilen-ID>.wav ab oder setze file für die Zeile. mp3 und wav funktionieren beide.
  • Erstelle einen stummen Entwurf: gib der Zeile einen seconds-Wert.

Die Münder werden aus diesem Audio berechnet, lege die Stimmen also vor dem Testen fest.

Optional: ambience, bgm, sfx und songs. Verwende nur Material, für das die Person die Rechte hat. Dieses Projekt generiert keine Musik. Ohne lizenzierte Musik lasse die Partitur weg und lasse Ambience und Soundeffekte den Film tragen.

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 stoppt mit einem Fehler, wenn ein sichtbarer Charakter spricht, aber sein Mund sich nicht bewegen kann – der am leichtesten zu übersehende Fehler. Betrachte jedes Standbild, bevor du den Test zeigst. Warte nicht, bis der gesamte Film fertig ist, um ihn jemandem zu zeigen.

Einen Charakter auf den Boden bringen: schätze ground, rendere ein Standbild und passe an. Das ist schneller als Berechnung.

Lasse die Shots nicht stillstehen. Gib jedem Shot eine Sache, die sich bewegt, es sei denn, ein Beat soll still sein: eine Schwenkung auf der Platte, ein bob oder shake, ein Zeichnungswechsel oder ein Overlay wie Regen. Beende den Film mit fade_out auf dem letzten Shot.

7. Gesamter Film und finale Überprüfung

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

Bestätige jeden dieser Punkte vor der Übergabe und sage deutlich, wenn du es nicht konntest:

  • Du hast einen echten Frame aus jedem Shot betrachtet
  • check_mouths.py meldet keine eingefrorenen Münder
  • Jeder Charakter sieht immer noch wie dieselbe Person in verschiedenen Shots aus (Gesicht und Proportionen sind wichtiger als Farbe)
  • Personen in einem Gespräch schauen sich an
  • Eine einzelne Zeichnung, die sich über den Bildschirm bewegt, hat einen bob oder mehr Zeichnungen, sonst wirkt sie wie ein Rutschen
  • Du hast es gehört. Wenn du nicht zuhören kannst, sage, dass der Audio nicht nach Gehör überprüft wurde

Ein vollständiges Beispiel

examples/rainy-slide in diesem Repository enthält die Prompts und die Shotliste eines fertigen 15-Sekunden-Films, und docs/tutorial.md erklärt ihn. Finde sie unter ../../examples/rainy-slide und ../../docs/tutorial.md von dieser Datei aus. Verwende sie als Modell, wenn jemand nach einem fragt.

Tempo

Faustregeln: Shots dauern durchschnittlich 3–5 Sekunden, Charaktere halten jede Zeichnung für 3–4 Frames (etwa 7 Zeichnungen pro Sekunde), mit häufigen Nahaufnahmen und übertriebenen Ausdrücken. hold ist die Anzahl der Frames pro Zeichnung.

Häufige Probleme

SymptomUrsache und Behebung
Körperfarben flackern beim MundwechselDie Variante wurde nicht durch prep_cels.py verarbeitet
Ein Gang oder Lauf pulsiert hoch und niedrigZeichnungen nicht separat skalieren. Ein Akteur teilt automatisch einen Maßstab. Füge auch align_head hinzu
Ein Requisit nimmt die falsche Farbe anEin Paletteneintrag ist zu nah. Entferne ihn oder senke SNAP
Der Mund bleibt während des Sprechens offenZwei-Zustands-Münder verwenden einen Schwellwert von 0,5. Überprüfe, ob das Audio gedämpft ist
Leise Wörter bleiben geschlossenEin lautes Wort setzt den Maßstab für seine Zeile. Füge ein _m2 hinzu oder senke mouth_open_at für die Zeile
Der Regen oder Wind ist nicht zu hörenAmbience ist standardmäßig leise. Gib ihm einen level_db, z. B. -35
Ständiges ZischenDer Ambience-Clip ist nur Rauschen. Ersetze ihn. Die Verstärkung ist begrenzt, also wird er nicht weiter verstärkt
Codex sagt, das Referenzbild wurde verlorenDie Bildgenerierung muss ihre erste Aktion sein. paint.py handhabt dies, also führe es erneut aus

Grenzen

Dieser Weg ist nicht geeignet für komplexe Kämpfe, lange durchgehende Action oder realistische Malerei.

Individual skills in this repo

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

Verwandte Skills