export-final
Assemble le fichier final. Arguments : slug $project, $platform remplace
output.platform si l'utilisateur souhaite un second livrable. Requête complète dans $ARGUMENTS. Un
placeholder $ vide signifie que la compétence s'est déclenchée automatiquement plutôt que d'être invoquée par / : prends
le projet depuis PIPELINE_STATE dans le contexte de session et indique celui que tu as choisi. Les noms
verbes suivent le contrat de build ; python engine/ve.py --help prévaut.
L'architecture de rendu, qui est établie
- Vidéo : un MP4/MKV par segment en cache, avec des paramètres d'encodage identiques, chacun commençant sur une
trame IDR, puis joints avec
-f concat -safe 0 -c copy. Vérifié sans perte et quasi instantané. - Audio : un passage continu sur toute la timeline en
pcm_s24le. Jamais mis en cache par segment. - Mux unique, encodant l'AAC exactement une fois.
Ne reconçois pas cela au moment de l'export. En particulier, ne le « simplifie » pas en un seul
filter_complex sur tous les segments : un graphe de 150 segments fait environ 19 000 caractères et environ
260 segments dépasse la limite de la ligne de commande Windows, produisant un processus impossible à lancer plutôt qu'une
erreur utile. Cela jette également le cache par segment, qui est la raison pour laquelle un second export
prend quelques secondes.
Les filtergraphs vont toujours dans un fichier et sont passés comme -/filter_complex fc.txt.
Inconditionnellement, pas seulement quand ils deviennent longs.
Étape 1 - pré-vol
Avant d'encoder quoi que ce soit :
- Exécute qc-pass. Un export sur un projet qui échoue au QC gaspille l'opération la plus longue du pipeline.
- Confirme
output.platform. Il détermine la cible de volume sonore, la résolution et la zone de sécurité des sous-titres. Si$platformdiffère deoutput.platform, ne mute pas silencieusement le projet - rends un second chemin de sortie et indique lequel est lequel. - Rapporte le plan : nombre de segments, nombre total d'images attendu, durée attendue, codec, et si les sous-titres et les graphiques sont incrustés dans cette passe.
Étape 2 - rendu des segments
python engine/ve.py render $project
Mis en cache par segment sous .cache/seg/, indexé par la clé forte de la source, les trames in/out,
les filtres, l'encodeur et les versions des outils. Seuls les segments modifiés sont re-rendus. --only seg_0012
rend un seul pour inspection.
Valeurs par défaut de l'encodeur : h264_nvenc, cq 20, preset p6. NVENC sur cette carte Ada est à peu près à parité
VMAF avec libx264 - en retard de 0,19 VMAF à 2 Mbps, en avance de 0,06 à 8 Mbps - tout en étant
2 à 4 fois plus rapide. C'est le bon réglage par défaut pour les aperçus et un choix défendable pour les versions finales. Passe à
libx264 uniquement si l'utilisateur demande une qualité maximale par bit et est prêt à attendre.
Les deux encodeurs étaient reproductibles octet par octet d'une exécution à l'autre sur cette machine, ce qui rend la mise en cache par segment adressée par contenu sûre.
Étape 3 - concat, mais protège-le d'abord
concat_compatible() s'exécute avant chaque concat -c copy, sans exception. En cas de
non-correspondance des paramètres, le démultiplexeur concat vous donne un fichier corrompu avec exit 0 - aucun
avertissement, aucune erreur, un fichier qui joue pendant dix secondes puis se désagrège. La vérification QC (c) est cette
vérification.
Elle compare la résolution, le format de pixel, le codec, le profil, le niveau, la base de temps, le taux d'échantillonnage et la disposition des canaux sur chaque segment. Une non-correspondance signifie qu'un segment a été rendu avec des paramètres différents - généralement une entrée de cache obsolète datant d'avant un changement de réglage de l'encodeur. Re-rends les contrevenants plutôt que de forcer le concat.
Étape 4 - audio et volume sonore
python engine/ve.py render $project
Puis en deux passes loudnorm vers la cible de la plateforme depuis output.loudnorm (YouTube : I
-14, TP -1,5, LRA 11 ; les autres plateformes diffèrent et se trouvent dans presets/formats/).
La passe 2 doit porter un -ar 48000 explicite. Sans cela, la sortie est silencieusement à 192 kHz -
la fréquence interne de loudnorm fuit dans la sortie, le fichier est quatre fois plus grand que prévu,
et certains lecteurs le rééchantillonnent mal. C'est le drapeau le plus souvent oublié de toute la chaîne.
Deux passes, pas une seule passe : le loudnorm en une seule passe est une estimation dynamique et se situe à un décibel ou plus de la cible sur un matériel avec une ouverture silencieuse, ce qui est le cas de chaque vidéo de tête parlante avec un fond.
Étape 5 - mux unique
Les étapes 2 à 5 sont toutes ve render $project : il rend ou réutilise les segments mis en cache, les concatène,
rend l'audio en un seul passage, lui applique loudnorm et muxe l'AAC 320k exactement une fois dans
projects/$project/out/final.mp4 conformément à output.path.
Ne ré-encode pas la vidéo au mux. Si quelque chose doit changer dans l'image, cela change au niveau du segment et le cache gère le reste.
Après le mux, ve render compose les incrustations rendues puis brûle l'ASS si
captions.burn_in - dans cet ordre, pour que les sous-titres soient au-dessus des graphiques. Les deux
ré-encodent le master, c'est pourquoi ve gfx et ve captions sont des choses que tu exécutes avant ve render, pas
après. Les exécuter après laisse un master une version en retard et rien ne t'avertit.
ve export est une étape distincte, ultérieure : elle exécute un QC complet, refuse en cas d'échec à moins que tu passes
--force, puis timbre une copie de livraison datée et écrit un .manifest.json à côté.
Étape 6 - vérifie le livrable, puis remets-le
Exécute les vérifications obligatoires sur le fichier de sortie réel, pas sur le plan :
- Le nombre d'images est égal à la somme de
(out_frame - in_frame)sur les segments activés. QC (a). - Le nombre d'échantillons audio est égal à
frames / fps * 48000. QC (b). - Le volume sonore intégré
ebur128est à moins de 0,5 LU de la cible de la plateforme, le pic vrai est sous le plafond. QC (f). - Le conteneur, la résolution, la fréquence d'images et la durée correspondent à
output. - Vérifie trois images : la première, une limite de segment au milieu, la dernière. Une image noire à une limite signifie qu'un segment a été rendu trop court.
Puis rapporte : chemin de sortie, taille du fichier, durée, LUFS mesuré et pic vrai, nombre d'images,
nombre de segments et combien de segments proviennent du cache. Définis stage à "export".
Deuxième livrable
Une coupe verticale n'est pas un recadrage du fichier final. C'est un output.platform différent,
ce qui signifie une cible de volume sonore différente, un préréglage de sous-titres différent et une zone de sécurité
différente, et généralement un passage narratif différent. Dis cela plutôt que de redimensionner le master 16:9.
Modes d'échec
| Symptôme | Cause | Correctif |
|---|---|---|
| La sortie joue puis se dégrade, ffmpeg a quitté avec 0 | Non-correspondance des paramètres dans concat | concat_compatible() avant chaque concat ; re-rends les contrevenants |
| Le master est à 192 kHz | Il manque -ar 48000 à la passe 2 de loudnorm | Ajoute-le et relance la passe 2 |
| Le processus d'encodage ne peut pas être lancé | Filtergraph sur la ligne de commande | Écris toujours fc.txt et passe -/filter_complex |
| Le volume sonore est à un décibel de la cible | Loudnorm en une seule passe | Deux passes |
| L'export est plus lent à chaque fois | Cache invalidé par un changement de réglage d'encodeur | Attendu ; confirme que le changement de réglage était intentionnel |
| Image noire à une coupe | Segment rendu trop court | Re-rends ce segment ; vérifie QC (a) |
| Voix plus calme dans le final que dans l'aperçu | amix sans normalize=0 | Corrige dans le graphe audio, re-rends l'audio |