3D-Kamera-Untertitel
Der After-Effects-Effekt (3D-Kamera, Tiefenschärfe, Text auf einem Pfad, Posterize Time 15, Bewegungsunschärfe), neu aufgebaut als deterministischer Frame-für-Frame-Maler für HyperFrames. Eine Uhr malt Platte, Maske und jedes Glyphen. Nichts ist eine CSS-Animation.
Wann verwenden / wann nicht
- Verwenden für eine statische Kameraeinstellung eines sprechenden Kopfes (Avatar oder echt), Querformat, mittlere Einstellung oder weiter, 5–20 s pro Stück. Die Wörter müssen in der Tiefe um den Sprecher herum performen.
- Nicht verwenden für einfache Untertitel, eine bewegte oder Handkamera (die Maske und die Platten-Transformation gehen von einer fixierten Einstellung aus), extreme Nahaufnahmen (kein Platz hinter oder um den Kopf) oder ein Motiv, das ein Person-Masking-Modell nicht trennen kann.
Anforderungen und Nebenwirkungen (vollständige Liste)
- Werkzeuge:
- Node 22+ und die HyperFrames-CLI, festgepinnt auf die getestete Version,
npx [email protected](Download vonregistry.npmjs.org). Verwenden Sie genau diese Version für jeden folgenden Befehl. ffmpegim PATH.- Python 3 mit
fonttools,brotli,numpy,pillow.
- Node 22+ und die HyperFrames-CLI, festgepinnt auf die getestete Version,
- Maske:
npx [email protected] remove-backgroundläuft lokal. Beim ersten Start lädt es das Personensegmentierungsmodell herunter (~170 MB) nach~/.cache/hyperframes/. - Renderzeit: Kompositionen laden GSAP 3.14.2 von
cdn.jsdelivr.netzur Vorschau- und Renderzeit. - Wortuhr: Jeder wortgenaue Transkribierer, den der Benutzer bereits lokal ausführt. Onset-Genauigkeit ist wichtig; einfaches Whisper startet zu spät.
- Schriftarten: Vom Benutzer bereitgestellte Dateien. Bestätigen Sie, dass die Lizenz die Einbettung erlaubt.
- Handgezeichneter Stil (optional): Benötigt die installierte und eingerichtete
p5-paint-animation-Fähigkeit (deren Setup lädt gepinntes Puppeteer, Chrome for Testing, p5 und p5.brush herunter).build-sprites.pyführt es kopflos aus; Frames werden in dasout/-Verzeichnis dieser Fähigkeit geschrieben und danach entfernt. - Nichts anderes: Keine Anmeldedaten, keine kostenpflichtigen Aufrufe, keine Uploads. Dateien werden nur in das Projekt geschrieben (
assets/,renders/).
Vorbereitung (einmal pro Aufnahme)
- Portion und Platte.
bash scripts/prep-take.sh <take.mp4> <start_s> <dur_s> <project>/assetserzeugt:portion.mp4: die Audioquelle.plate-tall.mp4: spiegeln-gepolstert, 240 px pro Seite, 480 px oben, 240 px unten, damit Whips, Trucks und Pull-backs niemals einen Rand zeigen.person.webm: die Alphamaske, gleiche Frames.- Das Skript prüft dann die Platte und Masse gegen die Portion (Größe, Bildrate, Frame-Anzahl) und bricht bei Abweichung ab.
- Wortuhr. Wortzeitmarken für die Portion, in Sekunden ab ihrem Start.
- Schriftarten. Wählen Sie 2–3 Rollen (Untertitel / Held / Ring), dann
python3 scripts/font-metrics.py assets/metrics.js key=font.woff2[@wght=…,opsz=…] ….- Eine variable Schriftart muss ihre Achsen hier übergeben UND in CSS fixieren (
font-variation-settings,font-optical-sizing: none). Andernfalls folgt die Browser-Optical Size der Größe und Wörter überlappen.
- Eine variable Schriftart muss ihre Achsen hier übergeben UND in CSS fixieren (
- Silhouette. Lesen Sie die Kopfbox und Schulterlinie aus der
person.webm-Alpha-Maske ab, bevor Sie etwas platzieren.
Build
- Kopieren Sie
assets/kit/{cam3d.js,tables.js,finish.js}undmetrics.jsin das Verzeichnisassets/des Projekts. references/worked-film.htmlist der vollständige Referenzfilm. Er hat zwei Einstellungen, einen Body-Wipe, beide Ringtypen, einen Fly-Through, ein Finale und die Grading; seine Medien sind nicht enthalten.references/recipes.mdenthält die tiefengestaffelten Gruppen, den gewickelten Ring, die Treppe und handgezeichnete Wörter.C3.init(metrics, {W, H}):- Die Linse behält das vertikale Sichtfeld des Tutorials (F = 1326.1·H/1080), sodass
tables.jsbei jeder Breite unskaliert angewendet wird. - Bei einem Frame breiter als 1440, addieren Sie
(W − 1440) / 2zuwipe.x.
- Die Linse behält das vertikale Sichtfeld des Tutorials (F = 1326.1·H/1080), sodass
Aufnahmegrammatik
Wählen Sie 4–6 Beats. Teilen Sie jede gesprochene Klausel in ihre eigene Gruppe.
| Beat | Build | Regel |
|---|---|---|
| Whip-in Punch-in | camA Tabelle (19 f von 502 px niedrig) dann ein linearer Creep | Plattenskalierung S0 1.1–1.3; der Frame landet nie |
| Tiefengruppen | 2–3 Untertitelgruppen pro Klausel bei D 1250 / 1500 / 2200 | nah = größer mit größerem Schatten; der Creep und Truck zeigen die Parallaxe |
| Held hinter | Held-Wort in der Hinter-Ebene auf Plattentiefe, masthead-artig über den Kopf | der Kopf versteckt die mittleren Buchstaben; ≥ 60 % bleiben lesbar; der Oberlängenbereich ist innerhalb des Frames |
| Parallax-Truck | swing-Segment, tx 420 | das alte Layout verblasst über 3 Schritte; das nächste Layout kommt durch Parallaxe an |
| Body-Wipe | die eigene Maske des Sprechers, brightness(0) blur(), Vorderkante von wipe.x | Einstellung A clip links vom Band, Einstellung B rechts; Pull-out auf beiden Seiten |
| Gewickelter Ring | horizontaler Kreis VOR dem Sprecher (Zentrum Z 2000), 11–16° von oben, sich drehend | Wörter treten klein an der Seite ein, wenn gesprochen, schwingen um die Front, setzen sich; unterer Bogen klappt um, um aufrecht lesbar zu sein |
| Fly-Through | Phrasen bei D 1500 / 2000 / 2500, Kamera schwingt zwischen ihnen | der Fokus folgt der Phrase |
| Treppen-Finale | Push-Segment; Untertitelwörter jeweils tiefer und kleiner diagonal | der Push treibt die nahen Wörter auseinander |
Regeln
- Bewegung:
- Text wird auf 15 fps posterisiert (seine eigene Animation und die Kamera, die er sieht). Platte und Maske bewegen sich jedes Frame.
- Bewegungsunschärfe ist 7 Geister über einen halben 15-fps-Schritt. Verwenden Sie
shutter: 0.5bei sich drehenden Ringen. - Untertitel gehen der Stimme um 0.2 s voraus, gesnappt auf das 15-fps-Raster:
fr(t) = 2·round((t − 0.2)·15). - Eintritte steigen um
ENTRY: Untertitel 30 px, Helden 110–260 px. Ringwörter erleichtern ihre letzten 30–44 px entlang des Pfades. Verwenden Sie den Überschwung vonRING_ENTRYnur, wenn noch kein Nachbar platziert ist.
- Tiefe:
- Jede Gruppe bekommt ihr eigenes D. Platte 3000, Untertitel 1250–2400, gewickelter Ring ≈ 1100–2700.
- Tiefenschatten
[6, 16, 0.5, 1500]skaliert als 1500/(D − cz). - DOF σ = 6.7·|D − focus|/D px bei 1080 hoch. Flache Untertitel sind auf 1.2 px begrenzt; Ringglyphen erhalten die volle Unschärfe.
- Größen:
size/risesind on-screen px bei der Zielkamera (tland). Sprites werden in ihrer on-screen-Größe gerendert. - Abstände:
- Ringtext wird immer durch
ringLine(on-screen-Vorrücken; Typ: track 1.10, Lücke 26–30; handgezeichnet: track 1.0, Lücke 28) geschickt. - Ein sich drehender Ring wird bei jeder Pose neu gelegt.
- Ringtext wird immer durch
- Okklusion:
- Ringe zeichnen vor dem Sprecher.
- Teilen Sie ein Wort in Hinter/Vorne-Instanzen (
side,zSplit) nur, wenn es ABSICHTLICH hinter dem Kopf vorbeilaufen soll.
- Lesbarkeit:
- Untertitel gehen über die dunkle Seite des Frames.
- Text, der Haut oder helle Kleidung kreuzt, erhält einen dunklen Halo.
- Keine abschließenden Punkte auf dem Bildschirm.
- Grading (optional):
finish.jsliefert Kurven, Sättigung 1.12 für Haut und Korn, das pro Frame neu gerollt wird. Setzen Sie die opake Szene (Platte + Hintergrundtext + Maske) in einen gefilterten Wrapper. Geben Sie dem Vordertext das gleiche Grading mit darübergelegtem Korn, damit ein in Hintergrund/Vorderteil geteiltes Wort eine Farbe behält (siehereferences/worked-film.html).
Stile
- Editorial: eine kondensierte Display-Serife, kursiv für Helden; eine Text-Serife für Untertitel; Cremeweiß plus ein Akzent.
- Fett: schwere Grotesk-Helden, leichte Untertitel, ein gesättigter Akzent (der Arbeitsfilm).
- Handgezeichnet: p5.brush Write-On-Sprites von
scripts/hand/build-sprites.py:- Jedes Wort schreibt sich selbst ab seinem Onset.
- Ringe platzieren Wörter als Ganzes, rotiert zur Tangente und skaliert durch Tiefe, auf einem größeren, flacheren Ring.
- Rezept in
references/recipes.md.
Überprüfen
npx [email protected] check . --no-contrast. Die Geisterebenen lösen die WCAG-Kontrastprüfung aus; die Whip- und Wipe-Nähte überlappen absichtlich.- Fügen Sie in der Vorschauseite
scripts/frame-bounds.jsein und führen Sie__frameBounds(0, dur)aus.- Es muss
[]zurückgeben: keine Gruppe außerhalb des Frames für 5+ Schritte, während sichtbar.
- Es muss
- Fügen Sie
scripts/glyph-gaps.jsein und führen Sie__glyphGaps(t)im Ruhezustand aus.- Keine Kreuzwortberührungen.
- Flache Wörter messen als eine Box (Unterlängen führen zu falsch-positiven Ergebnissen). Ein kursives f’s Überhang liest negativ. Wörter auf gegenüberliegenden Seiten des Wipe-Bands zeigen beide.
- Wortabstände: Der gerenderte Abstand zwischen Wörtern ≈ ein Leerraum-Vorrücken.
- Machen Sie einen Snapshot von jedem Beat, rendern Sie mit
npx [email protected] render . --crf 12und überprüfen Sie die Frames in voller Auflösung pro Beat.
Grenzen
- Maskenränder flackern bei feinen Haaren. Die gespiegelte Polsterung zeigt kurz während eines Whips.
- Ein Sprecher, der das Bild füllt, lässt wenig Platz im Hintergrund: gehen Sie auf Masthead-Höhe oder verstecken Sie sich hinter einer Schulter.
snapshot --atteilt sich eine Seite, sodass Korn nicht zwischen Aufnahmen neu rollt. Beurteilen Sie Korn anhand eines Renderings.- Das Rendern mit Grading und vielen Geisterebenen kostet etwa das 2-fache eines einfachen Renderings.