Video-Overlays
Verwandelt einen Rough Cut in eine Reihe animierter Overlays, die genau auf dem Frame landen, auf dem der Sprecher die jeweilige Sache sagt, plus eine Importdatei für Resolve.
Legen Sie hier Ihre Marke fest
Bearbeiten Sie diese Einstellungen einmalig in scripts/scene.html (der :root-Block am Anfang). Alles andere liest daraus.
| Einstellung | CSS-Variable | Standardwert |
|---|---|---|
| Akzentfarbe | --brand-accent (+ --brand-accent-rgb als r,g,b) | #4a90e2 |
| Helle Textfarbe | --brand-light (+ --brand-light-rgb) | #f2f2f2 |
| Dunkle Schriftfarbe | --brand-ink | #0d131a |
| Anzeigeschriftart (Überschriften, Zahlen) | --font-display | 'Anton','Bebas Neue',Impact,sans-serif |
| Textschriftart | --font-body | 'Inter',-apple-system,sans-serif |
Die Anzeigeschriftart muss lokal installiert sein (z. B. in ~/Library/Fonts), da die Clips offline in einem kopflosen Chrome gerendert werden. Anton und Bebas Neue sind auf Google Fonts kostenlos. Der interne Codename BLUE bezeichnet einfach „die Akzentfarbe".
Hausstil: In-Szene-Text. Keine Karten. Der Text lebt im Raum neben dem Kopf des Sprechers, große Titel flankieren den Kopf, Fragen werden beim Sprechen eingeblendet. Immer in Ihren Markenfarben und Ihrer Anzeigeschriftart.
Die eine Regel, die am wichtigsten ist: Halten Sie Grafiken hinter dem Kopf des Sprechers oder seitlich. Nichts vor dem Gesicht und keine Hintergrundfarbe. Diagramme befinden sich ebenfalls an der Wand neben dem Sprecher. Alles ist maskiert, sodass Hände vor den Grafiken vorbeigleiten können.
Ein Durchlauf erzeugt: N transparente .mov-Clips, PLACEMENT.txt, zwei .fcpxml-Dateien und eine kurze PREVIEW.mp4.
Standardmäßig kein Ton. Fügen Sie keine Musik oder Soundeffekte hinzu, es sei denn, Sie werden darum gebeten.
Stil-Standardwerte (nach Geschmack änderbar)
- Nichts erscheint, bevor es gesagt wird. Verankern Sie jeden Clip am wortgenauen Zeitstempel der Phrase, plus ca. 0,12 Sekunden, damit er kurz nach den Wörtern erscheint. Abschnitts-Timing wirkt früh.
- Kurz. 2,5 bis 6,5 Sekunden. Die meisten um die 3 Sekunden. Es sollte hin und her schneiden wie in Social-Media-Videos, nicht statisch sein.
- Hinter dem Kopf oder seitlich, niemals über dem Sprecher. Keine Karten, keine Hintergründe, kein Abdimmen. Das bedeutet, dass die Ecken-Chips, jede
full-*-Karte unddefinefür neue Videos nicht mehr verwendet werden. - Zeigen Sie dennoch den Mechanismus. Greifen Sie lieber zu einem Diagramm als zu einem Satz. Verwenden Sie die In-Szene-Diagrammtypen (
dots,flow,bars,compare,math), die an der Wand neben dem Sprecher platziert werden. - Teilen Sie alles mit zwei Hälften. Die alte und die neue Art sind zwei Clips. 10 % und 20 % sind zwei Clips. Drei Optionen sind drei Clips, die jeweils beim Nennen der Option erscheinen.
- Jede Zeile erscheint bei ihrem Wort. Listen, Nebenlinien und getippte Wörter haben versehene Offsets pro Zeile (
at,t) aus den Wortzeitstempeln, keine gleichmäßige Staffelung.scripts/plan.example.pyzeigt, wie es geht: Phrase zitieren, Stichwörter benennen, und es sucht sie. - Eine gute Mischung (etwa 48 Clips über 11 Minuten): etwa ein Viertel In-Szene-Diagramme (meist
flow), dannside,pair,type,list2,num. Sparen Sie sichpairfür die Pointe auf. - Große Titel werden um den Kopf herum platziert, nicht dahinter.
pairteilt jede Zeile an einer Wortgrenze in zwei Hälften, die den Kopf flankieren, mit einem Abstand von 1,9-fachen Breite des Gesichtsbereichs (Haare und Ohren eingeschlossen), skaliert, sodass beide Hälften auf dem Bildschirm bleiben. Daher benötigt jedepair-Zeile 2+ Wörter („EINE STUNDE", nicht „STUNDE"): ein einzelnes Wort kann nicht geteilt werden und landet versteckt."around": falseindatastellt das zentrierte Aussehen wieder her. Die konturierte Linie ist 150px groß mit einem 5px Rand und einer hellen Akzentfüllung (35 %), damit sie lesbar bleibt.
Bevor Sie beginnen: Ist der Schnitt endgültig?
Overlays sind an exakte Wörter gebunden, daher verschiebt jeder nachträgliche Trimmen jeden Clip. Wenn der Benutzer Rohmaterial übergibt oder der Schnitt noch nicht endgültig ist, führen Sie zuerst die paper-edit-Fähigkeit aus und platzieren Sie die Overlays auf der von ihr erstellten Timeline.
Pipeline
1. Holen Sie sich den Schnitt und untersuchen Sie ihn
Bitten Sie um einen Export aus Resolve (z. B. in ~/Movies/), oder um Rohmaterial auf <IHR_FILM_LAUFWERK> für einen Papierschnitt. Eine Videodatei ist in Ordnung; kein separater Audioexport nötig. Wenn Resolve geöffnet ist, lesen Sie die Timeline über das MCP aus, anstatt einen Export zu verlangen.
ffprobe -v error -show_entries format=duration -show_entries stream=codec_type,r_frame_rate -of default=nw=1 "<datei>"
Notieren Sie die Bildrate (der Renderer nimmt standardmäßig 23,976 = 24000/1001 an; ändern Sie FPSN/FPSD in render.mjs für andere Raten) und fragen Sie, ob die Timeline bei 00:00:00:00 oder 01:00:00:00 beginnt (Resolves Standard ist 01).
2. Transkribieren Sie mit Wort-Zeitstempeln
ffmpeg -y -i "<datei>" -ac 1 -ar 16000 -c:a pcm_s16le cut.wav
whisper-cli -m ~/.cache/whisper-models/ggml-small.en.bin -f cut.wav -oj -ml 1 -sow -of cut
-ml 1 -sow gibt ein Token pro Segment, was die exakte Verankerung ermöglicht. Finden Sie dann die Startzeit jeder Phrase, indem Sie Token-Läufe in cut.json abgleichen (transcription[].offsets.from ist ms).
3. Wählen Sie die Momente aus
Lesen Sie zuerst das gesamte Transkript. Zielen Sie auf ungefähr einen Clip pro 15 Sekunden Video ab. Für jeden benötigen Sie: die Ankerphrase, einen Typ und die kürzeste Dauer, die der Animation Zeit zum Erscheinen und Nachwirken gibt.
Stützen Sie den Inhalt auf das, was tatsächlich gesagt wurde, nicht auf schriftliche Notizen. Wenn Notizen „30 Minuten" sagen und auf Kamera „ungefähr eine halbe Stunde", gewinnt die Aufnahme, und teilen Sie dem Benutzer den Unterschied mit.
4. Schreiben Sie clips.json
Kopieren Sie scripts/clips.example.json als Vorlage. Ein Objekt pro Clip:
{"id":"06-math-10","start":52.96,"dur":3.6,"type":"dots","cue":"\"if 10 out of 100 meals are home cooked\"",
"data":{"lit":10,"pct":"10%","count":"10 meals"}}
Halten Sie es außerhalb des Skill-Ordners (ein Scratchpad-Pfad ist in Ordnung) und übergeben Sie es mit CLIPS=. start ist die rohe Phrasenzeit in Sekunden; der Renderer fügt selbst die 0,12 Sekunden Vorlauf hinzu. Die id-Reihenfolge legt die Dateireihenfolge fest, daher nummerieren Sie sie.
5. Rendern Sie einen sauberen Schnitt (erforderlich für die In-Szene-Typen)
Die In-Szene-Typen lesen die Kopfposition aus und schneiden den Sprecher aus einer Kopie des Schnitts ohne Overlays aus. Rendern Sie die endgültige Timeline aus Resolve mit allen Overlay-Clips deaktiviert, H.264 1080p, in den Scratchpad. In der API hat SetTrackEnable in Resolve 19 nicht funktioniert; item.SetClipEnabled(False) für jeden Clip in der Spur hat funktioniert. Das Rohmaterial muss online sein, daher muss das Filmlaufwerk gemountet sein; falls nicht, bitten Sie den Benutzer, es anzuschließen und auf das Einbinden zu warten, anstatt einen fertigen Master zu rendern (alte Overlays wären darin eingebrannt).
6. Rendern
cd <skill>/scripts && npm i # nur beim ersten Mal, installiert puppeteer-core
swiftc -O person.swift -o person # nur beim ersten Mal, der Matte + Kopffinder
TITLE="<videoname>" CLIPS=/pfad/zu/clips.json FOOTAGE=/pfad/zu/sauber.mp4 OUT_DIR="$HOME/Movies/<videoname>-overlays" node render.mjs
# nur einen oder wenige Clips:
ONLY=06-math-10,07-math-30 OUT_DIR=... node render.mjs
Etwa 10 bis 15 Sekunden Wandzeit pro Sekunde Overlay (pair ist langsamer, da es jedes Frame mattet). Es im Hintergrund laufen zu lassen und zwischendurch zu prüfen, ist die richtige Vorgehensweise. Es erstellt am Ende PLACEMENT.txt und beide .fcpxml-Dateien.
Überprüfen Sie IMMER über dem echten Filmmaterial vor einem vollständigen Render. node proof.mjs <sauber.mp4> <clips.json> out.jpg [email protected] [email protected] ... rendert einen Frame pro Clip (Präfix@Sekunden-im-Clip) über der tatsächlichen Aufnahme, inklusive Matte, zu einem Bild zusammengesetzt. Schauen Sie es sich an. Text, der aus dem Bild läuft, ein Titel, der die Augen kreuzt, Text über einem unruhigen Hintergrund: Das alles ist im Code unsichtbar, aber im Bild offensichtlich. Bei Diagrammen ist die Überlagerung über Grau immer noch in Ordnung.
Proof-Frames: Zuerst als PNG extrahieren. Das direkte Überlagern eines qtrle .mov auf eine lavfi-Farbquelle mit -ss ergibt einen leeren Frame. Extrahieren Sie den Frame (ffmpeg -ss 2.8 -i clip.mov -frames:v 1 f.png), und überlagern Sie dann das PNG.
Platzieren in Resolve: Duplizieren Sie die endgültige Timeline als YouTube Final, importieren Sie die movs in einen Overlays-Bin, und rufen Sie für jede AppendToTimeline mit trackIndex: 2 und recordFrame vom IN-Timecode aus PLACEMENT.txt auf (((h*3600+m*60+s)*24+ff), also 01:00:00:00 = 86400). Parsen Sie PLACEMENT.txt Zeile für Zeile (line.split()[0] ist die ID, [1] der Timecode). Ein über die gesamte Datei angewandter Regex könnte Kommentartext wie „60-second" als Clip-ID lesen und den Timecode der nächsten Zeile stehlen, sodass ein Clip stillschweigend nicht platziert wird. Überprüfen Sie, ob die Anzahl der platzierten Clips der Clip-Anzahl entspricht.
7. Vorschau, dann Übergabe
Erstellen Sie eine 10-15 Sekunden dauernde Vorschau über dem echten Filmmaterial, damit der Benutzer es beurteilen kann, bevor es eingefügt wird:
ffmpeg -y -ss <t> -t 11 -i "<schnitt>" -itsoffset <a> -i "<clip1>.mov" -itsoffset <b> -i "<clip2>.mov" \
-filter_complex "[0:v][1:v]overlay=0:0:eof_action=pass[v1];[v1][2:v]overlay=0:0:eof_action=pass[vo];[vo]scale=1280:-2[v]" \
-map "[v]" -map 0:a -c:v libx264 -crf 20 -preset veryfast -c:a aac PREVIEW.mp4
Die Original-Audio-Spur wird mit dem Filmmaterial mitgeliefert, was die Vorschau benötigt.
Geben Sie dann die Importschritte an (Datei > Import > Timeline > Import AAF, EDL, XML, wählen Sie die starts-01-Datei, kopieren Sie die Clips in eine Spur über dem Filmmaterial bei 01:00:00:00).
Arbeiten direkt in Resolve (bevorzugt, wenn Resolve geöffnet ist)
Wenn ein resolve-MCP-Server installiert ist (z. B. der von Drittanbietern stammende barckley75/resolve-claude-mcp), kommuniziert er mit der Scripting-API von Resolve Studio. Wenn die paper-edit-Fähigkeit ein ensure_resolve.sh mitliefert, führen Sie es zuerst aus, damit Resolve gestartet wird, falls es geschlossen ist. Mit Preferences > System > General > External scripting using: Local bevorzugen Sie dies gegenüber dem Export-Import-Tanz.
Was sich ändert:
- Kein exportierter Schnitt mehr nötig. Lesen Sie die geöffnete Timeline für ihre echten Timecodes, Bildrate, Startzeitcode und Clip-Anordnung aus und verankern Sie dann die Overlays daran. Das behebt die „Timecodes verschieben sich bei jedem neuen Trimmen".
- Kein manueller Import mehr. Platzieren Sie die gerenderten
.mov-Clips direkt auf einer Videospur. - Bessere Auswahl der Momente. Zu sehen, wo die Schnitte bereits fallen, bedeutet, dass Overlays mit dem Edit landen können, anstatt dagegen anzukämpfen.
- Es kann auch den Render starten, wenn die Overlays platziert sind.
Regeln für die Verwendung:
- Lesen, bevor Sie schreiben. Bestätigen Sie zuerst Projektname, Timeline-Name, Start- Timecode und Bildrate und teilen Sie sie dem Benutzer mit.
- Schreiben Sie niemals in die Master-Timeline. Duplizieren Sie sie zuerst und arbeiten Sie an der Kopie, sodass ein Fehler nichts kostet.
- Vermeiden Sie
execute_resolve_code, es sei denn, ein normales Tool kann die Aufgabe nicht erledigen. Es führt beliebigen Python-Code gegen die Projekte des Benutzers aus. Wenn es der einzige Weg ist, zeigen Sie zuerst den Code. - Nur lokale Sitzungen. Resolve muss auf diesem Mac laufen, daher funktioniert dies niemals in einer Cloud oder einem geplanten Durchlauf. Fallen Sie dort auf das FCPXML zurück.
- Der FCPXML-Pfad funktioniert immer noch und ist die Fallback-Option. Generieren Sie weiterhin beide Dateien; sie kosten nur Sekunden.
Audio-Transkription: Einige Resolve-MCP-Server haben ihre eigene mlx-whisper-Transkription, aber der obige whisper.cpp-Schritt ist mit dieser Pipeline erprobt.
Clip-Typen
Alles unten Gesagte ist für neue Videos nicht mehr aktuell (behalten, damit alte Videos neu geschnitten werden können). Vollbild-Typen malen einen soliden tintenfarbenen Hintergrund mit einem sanften Akzent-Schimmer, sodass sie den Sprecher vollständig verbergen. Chips sitzen unten links.
| Typ | Verwendungszweck | data |
|---|---|---|
full-dots | nicht mehr aktuell, verwenden Sie dots | lit, pct, count |
full-flow | nicht mehr aktuell, verwenden Sie flow | label, steps[], good |
full-compare | nicht mehr aktuell, verwenden Sie compare | title, left{label,value,sub}, right{...,hi}, vs |
full-bars | nicht mehr aktuell, verwenden Sie bars | title, bars[{label,value,value_label,hi}] |
full-math | nicht mehr aktuell, verwenden Sie math | parts[] (Operatoren x = + → werden in der Akzentfarbe dargestellt), sub |
full-pack | nicht mehr aktuell, verwenden Sie bars oder side | name, note, size 0-1, hi |
full-stat | nicht mehr aktuell, verwenden Sie pair | label, value, sub, hi |
full-title | nicht mehr aktuell, verwenden Sie pair oder type | title (<br> erlaubt), size, sub |
full-list | nicht mehr aktuell, verwenden Sie list2 | title, items[], step Sekunden |
chip | nicht mehr aktuell, verwenden Sie side oder num | num, title, sub, hi |
chip-stack | nicht mehr aktuell, verwenden Sie list2 | items[] |
Die nicht mehr aktuellen Typen werden weiterhin gerendert, um alte Videos neu zu schneiden.
In-Szene-Typen (Standard)
Keine Karten, der Text lebt im Raum neben dem Kopf des Sprechers, und große Titel gehen um den Kopf herum.
| Typ | Verwendungszweck | data |
|---|---|---|
pair | Ein Pointen-Titel: Konturlinie über dem Kopf, durchgezogene Linie in Stirnhöhe | top, bottom, outline (top/bottom) |
side | 2-3 kurze Zeilen neben dem Kopf, jede erscheint bei ihrem Wort | lines[], accent (Index, groß + Akzentfarbe), at[] |
type | Ein Zitat oder eine Frage, Wort für Wort eingeblendet, während es gesprochen wird | words[{w,t,hi,br}] |
define | nicht mehr aktuell: dimmt die Aufnahme. Verwenden Sie side oder pair | word, sub |
num | Umrandete Zahl zeichnet ein, Wörter daneben („01 plane die Woche") | num, lines[] |
list2 | Elemente, die links und/oder rechts neben dem Kopf aufgebaut werden | left[], right[], at[] (in Reihenfolge, zuerst links) |
In-Szene-Diagramme (gleiche Wandplatzierung und Matte):
| Typ | Verwendungszweck | data |
|---|---|---|
dots | Eine Rate von 100, Rasterfüllung neben dem Sprecher | lit, pct, count |
flow | Ein Prozess, Schritte von oben nach unten verkettet, der letzte in der Akzentfarbe | label, steps[], at[] optional |
bars | Zwei oder drei Zahlen nach Größe | title, bars[{label,value,value_label,hi}] |
compare | Zwei Optionen, je eine auf jeder Seite des Kopfes | left{label,value,sub}, right{...,hi} |
math | Eine Gleichung, die an der Wand heruntergelesen wird, Operatoren führen jede Zeile an | parts[], sub |
at und t sind Sekunden ab Clip-Start; bauen Sie sie aus den Wortzeitstempeln auf, damit jede Zeile bei ihrem Wort erscheint.
Diese benötigen FOOTAGE=, den Schnitt ohne Overlays (rendern Sie die Timeline aus Resolve mit deaktivierten Overlay-Clips). Der Renderer liest den Gesichtsbereich und ein Hintergrund-Helligkeitsraster für jeden Clip, sodass der Text eine leere Wand findet, die Seite wechselt oder schrumpft, wenn er aus dem Bild laufen würde, und auf hellem Hintergrund tintenfarben, auf dunklem Hintergrund hell wird. Er maskiert den Sprecher aus jedem Frame jedes In-Szene-Clips (Apple Vision Person Segmentation, person.swift), sodass Titel hinter dem Kopf sitzen und Hände vor den Grafiken vorbeigleiten können. Einmal kompilieren: swiftc -O person.swift -o person. Ohne FOOTAGE= wird ein grauer Hintergrund simuliert.
Beispiele
Jedes Beispiel enthält den Aufruf, einen Screenshot und den Clip-Typ. Beispiele sind in scripts/clips.example.json.
pair – Titel um den Kopf
{"type":"pair","data":{"top":"ONE HOUR","bottom":"IS ALL YOU NEED","outline":"top"}}
side – kurze Zeilen
{"type":"side","data":{"lines":["Efficient","Personalized","AI-Powered"],"accent":2,"at":[0.1,0.3,0.6]}}
type – Wörter tippen
{"type":"type","data":{"words":[{"w":"This","t":0.0},{"w":"is","t":0.2},{"w":"a","t":0.4},{"w":"quote","t":0.6,"hi":true}]}}
num – Zahl und Wörter
{"type":"num","data":{"num":"01","lines":["Plan","the","week"]}}
list2 – Elemente links/rechts
{"type":"list2","data":{"left":["Task A","Task B"],"right":["Result 1","Result 2"],"at":[0.0,0.5,1.0,1.5]}}
dots – Rasterfüllung
{"type":"dots","data":{"lit":35,"pct":"35%","count":"35 out of 100"}}
flow – Prozessschritte
{"type":"flow","data":{"label":"Process","steps":["Step 1","Step 2","Step 3"]}}
bars – Balkendiagramm
{"type":"bars","data":{"title":"Comparison","bars":[{"label":"A","value":10,"value_label":"10%","hi":false},{"label":"B","value":20,"value_label":"20%","hi":true}]}}
compare – Vergleich
{"type":"compare","data":{"left":{"label":"Old Way","value":"10%","sub":"inefficient"},"right":{"label":"New Way","value":"90%","sub":"efficient","hi":true}}}
math – Gleichung
{"type":"math","data":{"parts":["10","x","5","=","50"],"sub":"% of total"}}
Fazit
Diese Pipeline liefert präzise, markengerechte Motion Graphics für Talking-Head-Videos, die sich nahtlos in den Workflow des Sprechers einfügen. Die strikte Ausrichtung auf Wortebene stellt sicher, dass Overlays genau dann erscheinen, wenn sie relevant sind, und schafft so eine dynamische, ansprechende Zuschauererfahrung.