Was macht REEL-FROM-SCRIPT · v7?
Eine Fähigkeit zur Erstellung eines 9:16-Reels, das kunstvoll gestaltet wirkt und nicht fehlschlagen kann – aus einem Skript, das du nicht geschrieben hast, einer Referenz, die du rückentwickeln musst, und einem frischen Chat ohne Erinnerung an den vorherigen.
v5 hat Layouts ausgeliefert und das Design fest in sie einprogrammiert. v6 hat jede Zahl in PARAMS.json verschoben und einen Validator vor den Render-Vorgang gesetzt. v7 ist das, was zwei echte Reels v6 gelehrt haben – der Sechs-Farben-Feld-Zyklus, das Cover-Poster, die szenenweise Kartenanimation, zusammenhängende Szenen-Blöcke, adaptive Wipes, die Audio-Fallen und ein einzelnes ./build.sh + scripts/qc.py, das sich weigert, ein schlechtes Ergebnis auszuhändigen.
Das Versprechen: Die einzige Datei, die ein Mensch bearbeitet, ist
PARAMS.json. Das Einzige, was Nein sagen darf, istprepare.py/qc.py. Alles andere wird generiert, und jedes generierte Objekt ist mit einem einzigen Befehl reproduzierbar.
0 · Wenn du neu hier bist: die ersten 10 Minuten
export PATH=/home/user/node22/bin:$PATH # Node >= 22
cd <project> && ./build.sh --from render # oder folge §3 von oben
Dann lies in dieser Reihenfolge: §1 (wie der Look entsteht) → §3 (die Pipeline) → §6 (Design-Playbook) → §9 (Fehlerkatalog). Erfinde kein Layout: das Skelett ist das Design.
Tu niemals diese vier Dinge: eine Dauer eingeben (miss das VO), einen Hex- oder px-Wert in eine Komposition einfügen (ändere PARAMS.json), index.html von Hand schreiben (generiere es) oder ausliefern, ohne das Kontaktblatt angesehen zu haben.
1 · Warum die Ausgabe gestaltet aussieht (die sieben Gesetze)
Dies sind die tatsächlichen Entscheidungen hinter jedem guten Frame dieser Serie. Sie sind Regeln, kein Geschmack.
1. Ein Ankergitter, unten fixiert. Kicker → Hero → Body → Chip → Presenter. Die untere Hälfte bewegt sich nie: Der Chip sitzt immer auf dem gleichen y, der Presenter wird immer an der gleichen Stelle vom Frame beschnitten. Nur die obere Hälfte setzt sich neu zusammen. Deshalb wirken neun verschiedene Szenen wie ein Film.
2. Der Hero ist ein Wort, kein Satz. 1–3 Wörter, gesetzt in einer komprimierten Display-Schrift bei ~17–25 % der Framebreite, enger Zeilenabstand (0.88). Die vollständige Zeile kommt in den Chip (3–6 Wörter, das, was ein stummgeschalteter Zuschauer liest), das Detail in die Karte. Kannst du es nicht in 3 Wörtern sagen, besteht der Beat aus zwei Beats.
3. Jeder Beat bekommt einen anderen Hintergrund. Sechs Felder (Creme / Dunkelrot / Beinahe-Schwarz / Salbei / Marineblau / Lavendel), die so zyklisch durchlaufen werden, dass keine zwei benachbarten gleich sind. Der Farbwechsel ist die andere Hälfte des Übergangs. prepare.py schlägt fehl, wenn zwei aufeinanderfolgende Szenen ein Feld teilen.
4. Beweis, keine Dekoration. Eine Karte dient dazu, die Sache zu zeigen: eine Dateiliste, ein Diff, ein Browser, ein Upload, ein Messgerät. Wenn ein Beat kein Artefakt hat, ist er type-led und hat keine Karte. Eine Karte mit zwei Zeilen sieht kaputt aus; vier bis sechs Zeilen wirken bewusst (oder ein Mockup, das ≥ 55 % der Karte füllt).
5. Der erste Frame ist ein Poster. Szene 1 wird bei t=0 komponiert (data-cover="1"): Kicker, Hero, Karte und Charakter bereits auf dem Bildschirm, Chip landet bei 0,65 s. Ein Reel, das auf einem leeren Feld beginnt, verliert den Scroll.
6. Bewegung ist nur Transformation und landet früh. Einblendungen dauern 0,24–0,34 s, power2/3/4.out, und enden in der ersten Hälfte des Beats. Animiere niemals Textinhalte, tweene niemals eine Zahl, lass niemals eine 1,5-s-Szene 0,6 s mit einem Wipe verbringen. Ein langsames Driften des Hero hält die letzte Sekunde lebendig.
7. Ton ist Interpunktion, keine Tapete. ≤ 1 Cue pro Sekunde: ein Pop bei jedem Schnitt, Key-Ticks auf der UI, ein Riser bei den zwei größten Wendungen, ein Chime bei der Enthüllung, ein Notify/Ping beim CTA. Bett bei 0,15 unter einem −16 LUFS VO; Master −14 LUFS / ≤ −1 dBTP.
2 · Der Vertrag: was festgelegt ist, was dir gehört
Unveränderlich – validiert, nicht durch Gefühle editierbar
| Unveränderliche Eigenschaft | Durchgesetzt von |
|---|---|
| Jedes Text-/Hintergrundpaar lesbar | WCAG ≥ 4,5:1 bei 10 gerenderten Paaren + 6 Feldpaaren |
| Hero ist ein Hero und passt immer | ≥ 120 px, abgeleitete Größe, muss in --hero-lines in --hero-band passen |
| Hero berührt den Kicker nicht, berührt nie die Karte | abgeleitete Band + --gap, harter Fehler |
| Fließtext auf einem Handy lesbar | ≥ 24 px und ≥ bodyMin |
| Nichts versteckt sich unter der Plattform-UI | Chip-Boden ≤ Safe-Zone-Boden, ≥ 55 % nutzbar |
| Chip kann nie mit der Karte kollidieren | cardTop + cardHmax ≤ chipTop |
| Presenter wird vom Frame beschnitten, nie über dem Chip | presenterTop + h > 1.0, presenterTop ≥ chipBottom |
| Zwei aufeinanderfolgende Szenen teilen nie ein Feld | data-field wird aus jeder Komposition gelesen |
| Frame 0 ist ein Cover | data-cover + ein Schnappschuss-Gate |
| Eine andere Pose in jeder Szene | eine Posen-Datei pro Szene, bei der Überprüfung kontrolliert |
| Ergebnis ist abspielbar und laut genug | qc.py: Auflösung, fps, Frames, LUFS, True Peak, stille Löcher |
Variabel – wirklich deine: Palettenwerte (6 Felder + 4 Papiertöne, Kontrast erlaubt) · Format (9:16, 4:5, 1:1, 720p) · Safe-Zone-Einsätze · jedes Raster- und Typografie-Verhältnis innerhalb des Rahmens · Archetyp pro Szene · Anzahl der Szenen · Wörter · Dauer · Posen-Set · Cue-Sheet · Schriften auf der Festplatte.
Wenn du ein Layout willst, das der Validator nicht prüfen kann, änderst du das Skelett und fügst die Prüfung hinzu. Das ist der Preis der Freiheit, und deshalb kann die Ausgabe nicht schlecht sein.
3 · Die Pipeline (Reihenfolge ist nicht verhandelbar)
| # | Schritt | Befehl | Warum hier |
|---|---|---|---|
| 0 | Die Referenz rückentwickeln | §4 | du kannst einen Look nicht treffen, den du nicht gemessen hast |
| 1 | Fakten | — | eine Behauptung, die zu spät kommt, erzwingt eine Neuaufnahme |
| 2 | Skript → Abschnitte | assets/vo/sections.json | eine Idee pro Beat, 1,2–9 s |
| 3 | VO zuerst | python3 scripts/process_vo.py | timeline.json ist die Uhr; das Bild ist darauf geschnitten |
| 4 | Look | PARAMS.json | Palette, Format, Raster, Typografie-Minimum |
| 5 | Gate | python3 scripts/prepare.py | schlägt fehl bei Kontrast / Typ / Kollision / Feld-Rhythmus |
| 6 | Szenen | ./scenes.sh | ein new_scene.py-Aufruf pro Beat, Token werden eingefügt |
| 7 | Root | python3 scripts/build_index.py | zusammenhängende Blöcke, adaptive Wipes, kein handgetipptes index.html |
| 8 | Lint | npx --yes [email protected] lint | 0 Fehler ist ein Gate |
| 9 | Ansehen | npx … snapshot --at "0,1.5,4,…" | der einzige Schritt, der "korrekt, aber hässlich" erwischt |
| 10 | Rendern | npx … render --output renders/_raw.mp4 | ~1 m 45 s für 32 s bei 1080×1920, Software GL |
| 11 | Mixen | python3 scripts/mix_audio.py | VO + Bett + Cues → renders/master.wav (−14 LUFS) |
| 12 | Muxen + ausliefern | build.sh Schritt 6–7 | mp4 + .srt + Vorschaubilder, dann qc.py |
./build.sh führt 3 → 12 in einem Durchlauf aus. ./build.sh --from render überspringt das VO, wenn es bereits gemessen ist.
Schritt 3 im Detail – VO ist die Uhr
# ein Clip pro Abschnitt, benannt vo1.mp3 … voN.mp3 in assets/vo/
python3 scripts/process_vo.py
Es schneidet Stille, wendet atempo nur an, wenn script_target gesetzt ist, normalisiert jede Aufnahme auf −16 LUFS und schreibt dann assets/vo/timeline.json: Start/Dauer/Ende pro Abschnitt + root_duration. Nachgelagerte Schritte dürfen keine Dauer kennen, die nicht in dieser Datei steht.
Schreibe say in Devanagari mit englischen Fachwörtern in Latein (resume, job description, ATS score, DM) – eine hi-IN-Stimme bekommt die Prosodie richtig hin und spricht die englischen Wörter dennoch aus. caption ist das, was das .srt zeigt.
Schritt 7 im Detail – der Root ist mechanisch
build_index.py findet compositions/s*.html in numerischer Reihenfolge, liest die gemessenen Blöcke, macht sie zusammenhängend (0 → Schnitt → Schnitt → … → Root, damit kein schwarzes Loch entsteht, wo das VO eine 0,30 s Lücke hat), feuert einen Wipe 0,36 s vor jedem Schnitt in der Farbe der ankommenden Szene und hält die letzte Szene bis zum Ende des Audio-Tails. Ein Wipe wird auf 34–62 % der Länge einer kurzen Szene verkürzt – eine 1,4 s Szene kann keinen 0,62 s Wipe halten.
Schritt 11 im Detail – die zwei Audio-Fallen
alimiterhatlevel=truestandardmäßig: es nivelliert automatisch zurück auf die Obergrenze, also wird dein "Limiter" zu einem Kompressor mit Make-up-Gain und der Mix landet bei −12,5 LUFS, während du auf −14 zielst. Immerlevel=false.loudnormin einem linearen Durchlauf überschießt. Messe mitebur128, verschiebe um exakttarget − measured, dann limiter. Rechnen, das du überprüfen kannst, schlägt einen Filter, der rät.
4 · Phase 0 – Die Rückentwicklung eines Referenzvideos
Wenn die Anweisung "schau dir das an und mache es nach" lautet, miss es. Zehn Minuten, fünf Befehle:
ffprobe -v error -show_entries format=duration:stream=width,height,r_frame_rate,codec_type -of default=nw=1 ref.mp4
ffmpeg -i ref.mp4 -vf "fps=1,scale=400:-1,tile=6x6" -frames:v 1 sheet.jpg # der gesamte Film als ein Bild
python3 - <<'P' # die Feld-Palette, pro Sekunde
from PIL import Image; import glob
for f in sorted(glob.glob("frames/f_*.jpg"))[::2]:
im = Image.open(f).convert("RGB"); w,h = im.size
print(f[-7:-4], im.getpixel((3,3)), im.getpixel((w-4,3)))
P
ffmpeg -i ref.mp4 -vn -ac 1 -ar 16000 -c:a pcm_s16le audio.wav # für das Skript
Daraus auslesen: Dauer und Schnitt-Rhythmus (wie lang jeder Beat ist), die Feld-Palette (Ecken abtasten, nicht die Mitte), Typografie-Verhalten (kondensierte Großbuchstaben? Wort-für-Wort-Aufbauten? Hervorhebungsboxen?), Layout (wo der Charakter sitzt, wo der Textblock sitzt), UI-Artefakte (welche Mockups), Ton (Cue-Dichte). Diese sechs Zahlen sind die gesamte Art Direction.
Wenn die Anweisung eine Referenz, aber kein Skript gab, ist die Referenz das Skript: transkribiere das Audio (faster-whisper, int8, base-Modell → ~7 s für 32 s Hinglish) und lies die Bildschirmtexte von den Frames ab. Schreibe den Text nicht um – eine Serie hat eine Stimme.
Übersetze, kopiere nicht. Die Referenz hier war 1280×720; das Ergebnis war 1080×1920. Gleiche Palette, gleiche Typografie, gleiche Mockups – aber der Hero-Bereich, Chip-Anker und Presenter-Beschnitt wurden als Verhältnisse neu abgeleitet. Im 9:16 fallen die 8–10 Wörter umfassenden Blöcke der Referenz unter die 24-px-Körper-Mindesthöhe, also wird der Text anders aufgeteilt: Hero 1–3 Wörter, Chip die Zeile, Karte das Detail.
5 · Dateien
PARAMS.json die einzige Design-Datei
tokens.css generierter Beleg (nicht bearbeiten)
index.html generiert von build_index.py (nicht bearbeiten)
SKILL.md · COMPONENTS.md · README.md
build.sh die gesamte Pipeline
scenes.sh jede Szene, reproduzierbar
components/ 7 Kartenkörper, die du mit --card-body @… übergeben kannst
compositions/
_scene-base.html.tmpl DAS Skelett – null Literal hex, null Literal px
wipe.html der einzige Übergang
sN-*.html generiert von new_scene.py
_examples/ drei ausgearbeitete Szenen (nicht eingebunden: build_index liest nur compositions/s*.html)
scripts/
process_vo.py VO → timeline.json
prepare.py das Gate: Mindestwerte + Token-Injektion
new_scene.py Basis-Template → eine korrekte Szene
build_index.py Timeline + Szenen → Root
mix_audio.py VO + Bett + Cues → master.wav
make_deliverables.py .srt + Vorschaubilder
qc.py ein Befehl, BESTANDEN/FEHLGESCHLAGEN bei 10 Prüfungen
cutout.py · gen_sfx.py Assets
assets/{fonts,presenter,vo,sfx,music}/
6 · Design-Playbook (was du tatsächlich wählen solltest)
Beat → Archetyp. Beweis → card-led. Eine Zahl → stat-led (Tachometer, --digits). Eine Aussage, ein Übergang, eine Markenkarte → type-led. Hook und CTA sind fast immer card-led, weil beide ein Artefakt brauchen (die Dateiliste, die das Problem beweist; der Kommentarthread, der den CTA beweist).
Beat → Feld. Wechsle warm und kühl ab; wiederhole nie. Ein praktischer Zyklus für sechs Felder:
accent → ground → ink → secondary → tertiary → quaternary. Dunkle Felder (ink, tertiary) lassen den Presenter verschwinden, also geht der Halo dort auf 0,20 → 0,42 (das Skelett macht das aus data-field); verwende sie für die Tool-Enthüllung und den "KI macht die Arbeit"-Beat, wo die Dramatik hilft.
Beat → Pose. Gleicher Charakter, gleiches Outfit, eine Pose pro Szene, passend zur Emotion der Zeile:
Achselzucken (eine Frage) · Facepalm (das Problem) · Präsentieren (das Angebot) · Kinn (neugierig) · Erinnerung (Rückblick) · Daumen (der Gewinn) · Zeigen (ein Schritt) · Idee (der Aha-Moment) · CTA (die Aufforderung). Generiere eine fehlende Pose aus dem Basisbild und matte sie mit cutout.py; behalte die weiße Grundregel und den Oberschenkel-Beschnitt bei, damit sie sauber ausgeschnitten werden.
Wörter auf dem Bildschirm. Hero: das emotionale Verb oder die Zahl (SAME RESUME?, CUSTOMIZE KARO, TAILOR, ATS SCORE). Chip: der Satz, den ein stummgeschalteter Zuschauer braucht (har company mein bhej rahe ho?). Kartentitel: was das Artefakt ist (applied / 12 companies). Karten-Meta: eine kleine Tatsache (this week, matched 3 of 7).
Wenn ein Beat zu kurz zum Gestalten ist (1–2 s). Behalte die Szene, entferne die zweite Ebene: Hero + Chip + Presenter, type-led, eine Enthüllung. Quetsche keine Karte und keine gestaffelte Liste in 1,4 s – es wirkt wie ein Fehler.
Wenn ein Beat lang ist (8–9 s, normalerweise der CTA). Inszeniere drei Enthüllungen im Abstand von 1,8–2 s (Kommentar → DM → Link) und lasse ein langsames Driften den Rest tragen. Ein 8 s statischer Frame ist die mit Abstand häufigste Ursache für "sieht billig aus".
Übergänge. Ein Wipe, 0,34–0,62 s, Farbe = das Feld der ankommenden Szene, abwechselnde Richtung. Kein anderer Übergangstyp: Konsistenz ist es, was acht Schnitte wie gemacht aussehen lässt.
Die letzte Sekunde. Der letzte Frame muss ein gestalteter Frame mit dem Handle und der Website darauf sein – der Zuschauer, der dort pausiert, sollte handeln können.
7 · Audio-Playbook
| Moment | Cue | Gain |
|---|---|---|
| jeder Schnitt | pop | 0,50 |
| die zwei größten Wendungen | riser 0,3 s vor dem Schnitt | 0,28–0,30 |
| ein UI-Element trifft ein | click, key | 0,38–0,45 |
| eine Liste tickt ein | key ×N, 0,12 Abstand | 0,40 |
| eine Enthüllung / ein Score | chime | 0,36–0,42 |
| CTA | notify, dann ping 1,7 s später | 0,32–0,40 |
| falsch / abgelehnt | error (sparsam – es wirkt nur einmal komisch) | 0,30 |
Cue-Offsets sind abschnittsbezogen in assets/sfx/cues.json ("vo7+1.68"), sodass ein neu aufgenommenes VO das Design nicht ungültig macht. Platziere niemals einen Cue auf der ersten Silbe eines Wortes; ein Tick gehört 20–60 ms vor den Akzent. Cues schneiden, wenn sie fertig sind; ein 0,30 s Pop klingt bei 0,15 s schon ab – schneide das Tail ab und vermeide Überlappungen.
8 · Komponenten (7 Kartenkörper in components/)
Jede Karte akzeptiert --title, --meta, --body und manchmal --header, --foot. @filename ist Kurzform für --card-body @components/filename.
| Komponente | Wann verwenden | Aufbau |
|---|---|---|
browser | "sieh dir das Dashboard an" | Adressleiste + Inhalt – URL und Seite sind Parameter |
code | ein Diff oder ein Snippet | Nummerierte Zeilen, optional Einrückungstiefe, einzeilige Diff-Markierung |
list | eine Aufzählung | Stichpunkte mit Aufzählungszeichen (keine Nummern), automatisch hover-fähig |
stat | eine einzelne große Zahl + Beschriftung | --digits 3, optional --unit, wird immer animiert |
grid | ein Raster von Elementen (Galerie, Vergleich) | --cols 2 / --rows 3, jedes Element ist ein --cell |
upload | eine Datei- oder Upload-UI | Fortschrittsbalken, Dateiname, Größe, Status |
meter | ein Messwert / eine CPU / eine Latenz | Balken, Zeiger, Skalenbeschriftung |
lead | eine Zitat- oder Lead-Karte (kein Bild) | Großer Text, optional Quellenangabe |
none | kein Kartenlayer (type-led) | — |
Verwende @list aus PARAMS.json, um pro Szene eine Kartenkomponente anzugeben:
{
"scenes": [
{ "id": 1, "hero": "SAME RESUME?", "chip": "har company mein bhej rahe ho?", "cardBody": "@browser" },
...
]
}
9 · Fehlerkatalog (was schiefgeht und warum)
| Der gesamte Katalog | Symptom | Wahrscheinliche Ursache | Behebung |
|---|---|---|---|
| Der Wipe hat die falsche Farbe | build_index.py konnte data-field in s2 nicht lesen – s2 hat kein gültiges Feld | data-field in der Szene setzen und build_index.py erneut ausführen | |
| Der Wipe frisst den Beat | s1 ist 1,4 s lang, also wird der Wipe auf 0,34–0,48 s verkürzt. Wenn build_index.py immer noch auf 0,62 schaltet, hat timeline.json eine falsche Dauer | process_vo.py erneut ausführen, die Dauer prüfen | |
| Der Text ist auf dem Handy unsichtbar | bodyMin in PARAMS.json ist < 24 px gesetzt | auf 24 px oder höher setzen | |
| Der Charakter verschwindet gegen den Hintergrund | Halo ist 0 oder der Halo skaliert nicht mit data-field | halo-Regel in _scene-base.html.tmpl prüfen | |
| Die Karte überlappt den Chip | cardTop + cardHmax > chipTop | Abstände in PARAMS.json anpassen oder die Kartenhöhe reduzieren | |
| Das Audio klingt komprimiert/flach | alimiter hatte level=true | level=false in mix_audio.py setzen | |
| Das Reel hat am Ende Stille | root_duration ist kürzer als die letzte Szene + Audio-Tail | mix_audio.py erneut ausführen | |
| Der erste Frame ist leer | s1 hat kein data-cover="1" | data-cover="1" zur Szene hinzufügen | |
| Zwei aufeinanderfolgende Szenen haben die gleiche Hintergrundfarbe | prepare.py hat den Feld-Zyklus nicht validiert | prepare.py erneut ausführen | |
| Der CTA-Link funktioniert nicht | Die URL ist nicht in PARAMS.json gesetzt | ctaUrl in PARAMS.json setzen |
10 · Randfälle
Randfall: "Die Referenz ist 9:16, aber das Ausgabeformat ist 4:5"
Layout-Verhältnisse sind in PARAMS.json als Prozentsätze der Framebreite oder -höhe gespeichert. Minimale Änderung: Nur das format-Feld ändern – grid und type passen sich an. qc.py validiert das endgültige Seitenverhältnis.
Randfall: "Der Voice-Over-Künstler hat die Pausen nicht eingehalten"
process_vo.py hat eine optionale --trim-silence-Stufe (standardmäßig AN). Wenn das natürliche Timing wichtig ist (wie bei einem Comedy-Beat), deaktiviere sie mit PROCESS_VO_TRIM=0. Die Timeline passt sich an.
Randfall: "Ich habe 15 Szenen, aber die Referenz hatte 6"
Das Skelett ist für 1–18 Szenen ausgelegt. Die sechs Farben werden zyklisch durchlaufen; prepare.py stellt sicher, dass kein benachbarter Beat die gleiche Farbe hat. Bei 15 Szenen könnten einige Farbtöne weiter auseinander liegen – ziehe in Betracht, die Palette auf 8 zu erweitern (füge sky und rose zu den sechs Standardfarben hinzu).
Randfall: "Der Charakter hat in jeder Szene das gleiche Outfit, aber die Referenz hatte Kostümwechsel"
cutout.py kann mehrere Posen aus einem einzigen Basisbild erzeugen, aber die Kleidung ist gleich. Für Kostümwechsel benötigst du separate png-Dateien mit Matte in assets/presenter/. Das Skelett wählt die Pose über --presenter-src – eine Szene, die nicht gesetzt ist, verwendet den Standard.
Randfall: "Das Reel wird auf LinkedIn gepostet, wo die Safe-Zone anders ist"
PARAMS.json hat einen safeZone-Block mit top, bottom, left, right als Prozentsätzen. Setze sie auf LinkedIn-Werte (oben 12 %, unten 18 %, Seiten 6 %) und führe prepare.py erneut aus – es schlägt fehl, wenn die UI-Plattform den Inhalt überdeckt.
11 · "Ich muss es nur einmal machen" – Kurzanleitung
# 1. Repository klonen (oder von einer .cursorrules-Datei bootstrappen)
git clone <repo> && cd <project>
# 2. Referenzvideo messen (§4)
# 3. PARAMS.json anpassen (Palette, Format, Text) – das ist das gesamte "Design"
# 4. VO-Clips in assets/vo/ ablegen – benannt vo1.mp3 … voN.mp3
# 5. Pipeline ausführen
./build.sh
# 6. renders/_raw.mp4 + renders/master.wav + renders/captions.srt prüfen
# 7. Ausliefern
python3 scripts/make_deliverables.py --output renders/final.mp4
qc.py läuft automatisch in build.sh und schlägt fehl, wenn eine der 10 Prüfungen nicht bestanden wird. Umgehe es nicht – die Prüfung ist das, was die Ausgabe "kunstvoll gestaltet" nennt.
12 · Frühere Versionen
| Version | Neuerung |
|---|---|
| v5 | Erste dedizierte Reel-Pipeline; Layouts fest einprogrammiert |
| v6 | PARAMS.json eingeführt; prepare.py hinzugefügt; alle Zahlen externalisiert |
| v7 | Sechs-Farben-Feld-Zyklus; Cover; per-Szene-Kartenanimation; zusammenhängende Blöcke; adaptive Wipes; Audio-Fallen behoben; qc.py hinzugefügt |