Was macht 动效 KINETIC?
Ein visuelles Sprachsystem + Zero-Dependency Frame-für-Frame-Renderer. Jeder Frame ist eine reine Funktion der Zeit: Bild, Untertitel, Soundeffekte und Musik teilen sich eine einzige Zeitachse, ohne manuelles Keyframing.
Es wurde aus zwei viralen Kinetic-Typografie-Videos extrahiert (siehe die Analyse in references/viral-laws.md) und bereits in tasks/opus-kinetic-20261001/ für ein komplettes Video getestet (examples/opus-kinetic/).
Fünf Gesetze (Jeder Shot muss sie erfüllen)
- Ein Objekt pro Satz: Jeder semantische Beat bekommt ein Objekt, das der Zuschauer „auf einen Blick“ erkennt – Leute aus der Content-Erstellung erkennen Auswahlrahmen, Wellenformen, Keyframes, Zeitleisten, Renderbalken, Lippen-Sync-Bars und Prompt-Boxen. Auch die Bewegungsart muss sinnvoll sein: „nicht vorhanden“ wird durchgestrichen, „umwerfen“ wird umgestoßen, „hinter den Rücken verstecken“ wird wirklich hinter der Person versteckt.
- Beat-Timing: Große Buchstaben fallen auf die Silbe, die ausgesprochen wird (
at('Wort')); jeder Schnitt in reinen Bildsequenzen liegt auf einem Musik-Beat (beat(k)); jede sichtbare Aktion hat einen passenden Soundeffekt, der nur auf sichtbare Aktionen reagiert. - Eine durchgehende Linie: Ein Lichtstrahl zieht sich durch das gesamte Video – beginnt als eingebrannter Scanline, wird zum Auswahlrahmen, zur Wellenbasis oder zu einem dynamischen Element, das durch die Szene gleitet, und endet in einem Punkt, der den Abspann schreibt und dann erlischt. Verwandle statt harter Schnitte.
- Spannung und Entspannung: Nach dichten Sequenzen muss eine ruhige Phase kommen (ein komplett stiller Beat, ein kleiner Text auf cremeweißem Hintergrund); eine sich ständig ändernde Zahl baut Spannung auf (in diesem Video: „Manuelle Keyframes: 0“).
- Qualität: Streng vierfarbig, Subframe-Bewegungsunschärfe, Glühen, chromatische Aberration-Pulse, Clustered-Partikel; kleine, werkzeugartige Anmerkungen, die den Zuschauer zum Pausieren einladen.
Sprachspezifikationen
| Feature | Spezifikation |
|---|---|
| Farbpalette | Nacht #0A0A0D · Knochenweiß #F1EDE4 · Signalorange #FF5A1F · Kobaltblau #3448FF (nur für „Maschine/Daten“) · Grau #8B8983 · Graphit #26262C |
| Schriftarten | Noto Sans SC (Chinesisch, 900 für große Wörter / 500 für Fließtext) · Archivo VF (Latein & Ziffern) · JetBrains Mono (Anmerkungen) · Songti nur für ruhige Beats |
| Mindestschriftgröße (1920×1080) | Anmerkungen ≥28px, Erklärungen ≥36px, große Wörter ≥76px; muss auch bei Skalierung auf 390px Breite lesbar sein |
| Acht Aktionen → Soundeffekte | Einbrennen click · Linie ziehen zip · Scannen scan · Auswählen blip/select · Wort fallen impact/hit · Dekodieren tick · Einsaugen suck · Schockwelle drop |
| Personenstatus | Vollbild (W 1.0 / M ~1.2 / C ~1.4 mit Jump-Cuts und Zooms) · Auswahlrahmen ziehen zu Fenster · kleines Fenster in der Ecke (unten rechts) · Freistellung in die Szene (Text hinter Person) |
| Untertitel | Ein natürlicher Satz = eine Karte, keine Satzzeichen, zusammenhängend geschrieben (z.B. Opus5.5); einfarbig nachtschwarzer Hintergrund, 8px abgerundete Ecken, 46px Höhe; ungelesen grau → gelesen knochenweiß mit kontinuierlichem Farbverlauf, der vorderen Kante mit Signalorange-Licht |
| Sicherheit | Jeder Text/Grafik vor der Person muss ≥30px Abstand zum echten Kopfrahmen (inkl. Hut) halten; Text hinter der Person (unter der Freistellungsebene) ist nicht eingeschränkt. Mit qa_face.py überprüfen, nicht per Augenmaß |
Workflow (Detaillierte Befehle in references/pipeline.md)
- Skript → Beat-Tabelle: Zuerst natürliches Talking-Head-Skript schreiben, dann für jeden semantischen Beat ein Objekt auswählen (references/devices.md). Das Skript nicht für Effekte ändern.
- Voice-Over & Person: Nach dem Projekt-Workflow generieren (Fish Audio → HeyGen usw.). Echte Aufnahmen direkt verwenden.
- Alignierung:
tools/align_script.py– Skript als Grundlage, ASR nur für Timings; CJK-globales Align + Silent-Peak-Interpolation (ASR zieht oft das erste Zeichen eines Satzes in die vorherige Pause und behandelt den Punkt in5.5als Satzende). - Schnitt:
tools/build_edit.py– Globale Zeitlupe/Zeitraffer (Bild und Ton synchron, Lippenbewegung nicht betroffen), lange Atempausen zu Jump-Cuts komprimieren, reine Bildsequenzen einfügen, gibt eine einzigetimeline.jsonaus (alle nachgelagerten Tools verwenden nur diese). - Personenmaterial: Frames extrahieren →
tools/vision_analyze.swift(Vision-Porträt-Maske + Gesichts-/Mundrahmen) →tools/prep_media.py mattes|faces|thumbs|barcode. - Film schreiben: Ein
film.js-Modul (siehe Beispiel). Jedes Element wird anat('Wort')oderbeat(k)verankert; verwende das Vokabular ausengine/devices.js;ev(t, 'sfx')registriert Soundeffekte und Post-Processing-Pulse an derselben Stelle. - Validierung:
render.mjs --mode stillsfür Einzelbilder →--mode qa+qa_face.py(0 Verstöße erforderlich). - Audio:
render_dialog.py(Lautstärke der verschiedenen Quellen anpassen) →--mode cues→sfx.py→mix.py(Musik an Beat-Punkten schneiden, Stimme leiser, wenn keine Stimme lauter, stille Beats, statischer Gain + True-Peak-Limiter auf Ziellautstärke). - Finales Video:
render.mjs --mode framesin verlustfreie Blöcke rendern → Einmal H.264-Encodierung → Projekt-Checkliste.
Wie man echte Aufnahmen verwendet
Gleiche Methode: Freistellen, große Buchstaben hinter der Person durchlaufen lassen, Zahlen aus dem Skript in sichtbare Zähler/Fortschrittsbalken/Kreise verwandeln, bei Jump-Cuts Zooms einfügen, ursprüngliche Lautstärke anpassen. Das 10-Sekunden-Beispiel ist eine echte 4K-Aufnahme (references/pipeline.md).
Cover (3:4 / 4:3)
Vom selben Engine gerenderte Standbilder mit dem gleichen Look (Befehle in references/pipeline.md, Code in examples/opus-kinetic/cover.js):
- Person: Ein Frame aus dem digitalen Avatar-Footage auswählen – gerade Gesicht, offene Augen, natürliches Lächeln. Zuerst mit
faces.jsonl(Mundrahmen-Seitenverhältnis und Gerade-Gesicht-Wert) vorfiltern, dann visuell prüfen. Verlustfreier Frame-Schnitt →vision_analyze … 1.0(volle Auflösung Maske) →prep_media.py cutout(Wandfarbe von Haaren und Hutkrempe trennen, damit auf dunklem Hintergrund keine weißen Ränder entstehen). - Layout: Titel ≥150 px (basierend auf 1080 Breite), auch bei Skalierung auf 180 px Breite lesbar; Text im fertigen Video hinter der Person (3:4 mit Magazin-Stil, Hutkrempe drückt auf die Unterkante des Textes); am Ende des Titels ein Lichtpunkt. Maximal 2–3 kleine Objekte aus dem Video (Auswahlrahmen-Griffe, Ebenen-Label, durchgestrichene REC, eine Statistik). Text und Hutkrempe sollten sich nicht berühren: entweder klar überlappen oder ≥40 px Abstand halten.
- Sicherheit & Plattform:
--mode qa+qa_face.pymuss 0 Verstöße ergeben; ca. 10% unten für Plattform-Overlays (Views, Timestamps). - Das Modul ruft
setSize(w, h)in der ersten Zeile auf; Layout-Zahlen basieren auf der Gesichtsmitte; ein anderer Frame erfordert keine Code-Änderung.
Bereits gemachte Fehler (Nicht wiederholen)
- ASR überspringt manchmal den Anfang von Sätzen: Vor dem ASR-Processing 1 Sekunde Stille voranstellen, dann wieder entfernen.
- Der Punkt in Versionsnummern (
5.5) ist kein Satzende; Alignierung und Untertitel müssen als Dezimalpunkt behandelt werden. ffmpeg -ss … -c copyspringt zum vorherigen Keyframe, was den Schnittpunkt ungenau macht; für genaue Startpunkte dekodieren und mit Kreuzkorrelation überprüfen.- Frame-Cache gibt ImageBitmap frei: Für lang genutzte Bilder (Thumbnails, Point-Cloud-Quellen)
loadImageseparat verwenden. - TTS-Spitzen sind sehr hoch (PLR bis zu 24 dB); direktes Anheben der Lautstärke führt zu Clipping; zuerst dynamische Lautstärke-Normalisierung (mit True-Peak-Limit), dann mischen.
- zsh teilt Variablen nicht an Leerzeichen auf: Für das Rendern in Blöcken Bash-Skripte verwenden.
- Dynamisches
loudnormlässt das Verhältnis von Stimme zu Musik „atmen“; Mastering verwendet nur statischen Gain + Limiter. - Wenn Musik auf vollständige WAV umgestellt wird, können Inhalte über 19 kHz (plus vom Limiter selbst erzeugte) den True-Peak nach AAC-Encoding um ~1 dB erhöhen:
loudness.lowpass: 19000inmix.jsonam Ende der Mastering-Kette platzieren. - Vor dem Wechsel von der Vorschau zur Vollversion die Alignierung mit Kreuzkorrelation überprüfen (Epidemic-Vorschau und WAV sind sample-genau), dann je nach Lautstärkeunterschied
fullDbfeinjustieren, damit das Verhältnis von Stimme zu Musik mit der genehmigten Version übereinstimmt.