export-final
Setze die fertige Datei zusammen. Argumente: $project Slug, $platform überschreibt
output.platform, falls der Benutzer ein zweites Deliverable möchte. Vollständige Anfrage in $ARGUMENTS. Ein
leerer $-Platzhalter bedeutet, dass das Skill automatisch ausgelöst wurde und nicht per Slash aufgerufen wurde – dann
nimm das Projekt aus PIPELINE_STATE im Session-Kontext und gib an, welches du ausgewählt hast. Die
Verb-Namen folgen dem Build-Vertrag; python engine/ve.py --help gewinnt.
Die Render-Architektur, die festgelegt ist
- Video: eine gecachte MP4/MKV pro Segment, identische Encode-Parameter, jedes beginnend auf einem
IDR-Frame, dann zusammengefügt mit
-f concat -safe 0 -c copy. Verifiziert als verlustfrei und nahezu sofort. - Audio: ein kontinuierlicher Durchlauf über die gesamte Timeline in
pcm_s24le. Niemals pro Segment gecacht. - Einmal muxen, AAC genau einmal encoden.
Entwirf dies zur Exportzeit nicht neu. Insbesondere: Vereinfache es nicht in einen einzigen
filter_complex über alle Segmente: Ein Graph mit 150 Segmenten ist etwa 19.000 Zeichen lang und bei etwa
260 Segmenten läuft die Windows-Kommandozeile über, was einen nicht startbaren Prozess erzeugt, nicht
etwa einen hilfreichen Fehler. Außerdem wird damit der Cache pro Segment weggeworfen, was der Grund ist, warum ein zweiter
Export Sekunden dauert.
Filtergraphen gehen immer in eine Datei und werden als -/filter_complex fc.txt übergeben.
Bedingungslos, nicht nur wenn sie lang werden.
Schritt 1 – Preflight
Vor dem Encode von irgendetwas:
- Führe QC durch. Ein Export über ein Projekt, das die QC nicht besteht, verschwendet den längsten Vorgang in der Pipeline.
- Bestätige
output.platform. Sie bestimmt das Loudness-Ziel, die Auflösung und den Sicheren Bereich für Untertitel. Wenn$platformvonoutput.platformabweicht, mutiere das Projekt nicht stillschweigend – rendere einen zweiten Ausgabepfad und gib an, welches welches ist. - Berichte den Plan: Segmentanzahl, erwartete Gesamtframes, erwartete Dauer, Codec und ob in diesem Durchlauf Untertitel und Grafiken eingebrannt werden.
Schritt 2 – Segmente rendern
python engine/ve.py render $project
Gecacht pro Segment unter .cache/seg/, indexiert mit dem starken Schlüssel der Quelle, In/Out-Frames,
Filtern, Encoder- und Tool-Versionen. Nur geänderte Segmente werden neu gerendert. --only seg_0012
rendert eines zur Inspektion.
Encoder-Standardeinstellungen: h264_nvenc, cq 20, preset p6. NVENC auf dieser Ada-Karte ist ungefähr auf VMAF-
Parität mit libx264 – um 0,19 VMAF hinterher bei 2 Mbit/s, um 0,06 vorn bei 8 Mbit/s – und läuft dabei
2–4× schneller. Es ist die richtige Voreinstellung für Vorschauen und eine vertretbare für Finals. Wechsle zu
libx264 nur, wenn der Benutzer maximale Qualität pro Bit wünscht und bereit ist zu warten.
Beide Encoder waren auf diesem Rechner Lauf-zu-Lauf byte-reproduzierbar, was den inhaltsadressierten Segment-Cache sicher macht.
Schritt 3 – Concat, aber zuerst absichern
concat_compatible() wird vor jedem -c copy Concat ausgeführt, ohne Ausnahme. Bei einer
Parameter-Abweichung liefert der Concat-Demuxer eine korrupte Datei mit exit 0 – keine Warnung, kein
Fehler, eine Datei, die zehn Sekunden läuft und dann auseinanderfällt. QC-Prüfung (c) ist genau diese Prüfung.
Sie vergleicht Auflösung, Pixelformat, Codec, Profil, Level, Zeitbasis, Abtastrate und Kanallayout über alle Segmente hinweg. Eine Abweichung bedeutet, dass ein Segment mit anderen Parametern gerendert wurde – meist ein alter Cache-Eintrag aus der Zeit vor einer Änderung der Encoder-Einstellungen. Rendere die betreffenden Segmente neu, anstatt den Concat zu erzwingen.
Schritt 4 – Audio und Loudness
python engine/ve.py render $project
Danach zwei Durchgänge loudnorm auf das Plattform-Ziel aus output.loudnorm (YouTube: I
–14, TP –1,5, LRA 11; andere Plattformen unterscheiden sich und stehen in presets/formats/).
Durchgang 2 muss ein explizites -ar 48000 mitführen. Ohne dies ist der Ausgang stillschweigend 192 kHz –
loudnorms interne Rate sickert in den Ausgang, die Datei ist viermal größer als erwartet,
und manche Player resamplen sie schlecht. Dies ist das am häufigsten übersehene Flag in der gesamten Kette.
Zwei Durchgänge, nicht einer: Loudnorm mit einem Durchgang ist eine dynamische Schätzung und liegt ein Dezibel oder mehr vom Ziel entfernt bei Material mit einem leisen Einstieg – was jedes Talking-Head-Video mit einem Hintergrund ist.
Schritt 5 – Einmal muxen
Die Schritte 2 bis 5 sind alle ve render $project: es rendert die gecachten Segmente oder nutzt sie wieder, fügt sie
zusammen, rendert das Audio in einem Durchlauf, wendet Loudnorm an und muxt AAC 320k genau einmal in
projects/$project/out/final.mp4 gemäß output.path.
Code das Video beim Mux nicht neu. Wenn sich am Bild etwas ändern muss, ändert es sich auf der Segment-Ebene und der Cache erledigt den Rest.
Nach dem Muxen setzt ve render die gerenderten Overlays zusammen und brennt dann die ASS ein, falls
captions.burn_in gesetzt ist – in dieser Reihenfolge, damit Untertitel über Grafiken liegen. Beide
encodieren das Master neu, weshalb ve gfx und ve captions Dinge sind, die du vor ve render ausführst, nicht
nachher. Wenn du sie nachher ausführst, bleibt das Master eine Version zurück und nichts warnt dich.
ve export ist ein separater, späterer Schritt: es führt eine vollständige QC durch, verweigert bei
Fehlern, sofern du nicht --force übergibst, stempelt dann eine datierte Auslieferungskopie und schreibt eine
.manifest.json daneben.
Schritt 6 – Überprüfen des Deliverables, dann übergeben
Führe die obligatorischen Prüfungen an der tatsächlichen Ausgabedatei durch, nicht am Plan:
- Frame-Anzahl entspricht der Summe von
(out_frame - in_frame)über aktivierte Segmente. QC (a). - Audio-Sample-Anzahl entspricht
frames / fps * 48000. QC (b). ebur128Integrated Loudness innerhalb von 0,5 LU des Plattform-Ziels, True Peak unterhalb der Obergrenze. QC (f).- Container, Auflösung, Bildrate und Dauer stimmen mit
outputüberein. - Stichprobenartig drei Frames prüfen: erster, eine Segmentgrenze in der Mitte, letzter. Ein schwarzer Frame an einer Grenze bedeutet, dass ein Segment zu kurz gerendert wurde.
Dann berichten: Ausgabepfad, Dateigröße, Dauer, gemessene LUFS und True Peak, Frame-Anzahl,
Segment-Anzahl und wie viele Segmente aus dem Cache kamen. Setze stage auf "export".
Zweite Deliverables
Ein vertikaler Schnitt ist kein erneuter Zuschnitt der fertigen Datei. Er ist eine andere output.platform,
was ein anderes Loudness-Ziel, eine andere Untertitel-Voreinstellung und einen anderen
sicheren Bereich bedeutet, und meist einen anderen Story-Durchlauf. Sage das, anstatt das 16:9-Master zu skalieren.
Fehlermodi
| Symptom | Ursache | Behebung |
|---|---|---|
| Ausgabe läuft, bricht dann ab, ffmpeg beendet mit 0 | Parameterkonflikt beim Concat | concat_compatible() vor jedem Concat; betreffende Segmente neu rendern |
| Master ist 192 kHz | Loudnorm-Durchgang 2 fehlt -ar 48000 | Hinzufügen und Durchgang 2 wiederholen |
| Encode-Prozess startet nicht | Filtergraph in der Kommandozeile | Immer fc.txt schreiben und -/filter_complex übergeben |
| Loudness ein Dezibel vom Ziel entfernt | Ein-Durchgang-Loudnorm | Zwei Durchgänge |
| Export wird jedes Mal langsamer | Cache durch geänderte Encoder-Einstellung ungültig | Erwartet; bestätige, dass die Änderung beabsichtigt war |
| Schwarzer Frame an einem Schnitt | Segment zu kurz gerendert | Dieses Segment neu rendern; QC (a) prüfen |
| Stimme leiser im Finale als in der Vorschau | amix fehlt normalize=0 | Im Audio-Graph korrigieren, Audio neu rendern |