Que fait Pré-rendu : visuels générés et séquences stabilisées ?
Cinq routes, un ensemble de règles communes. Une pièce générée par code devient une séquence, placée comme une video : lisez-la d'abord. Un SVG fixe devient un PNG, placé comme une image : passez à la route SVG. Une animation Lottie devient aussi une séquence, dessinée avec un nouveau lecteur par image : passez à la route Lottie. Une scène 3D devient une séquence transparente ou un PNG fixe : passez à la route scène 3D. La stabilisation de source vidéo crée un nouveau clip : passez à la route stabilisation. Tout s'exécute en dehors du rendu, donc chaque peintre décode les mêmes pixels.
Montagent n'a pas de fichier de shader ou de script (ADR-0017). Un look en dehors de la liste des effects est dessiné dans votre propre code, encodé une fois comme séquence, et placé comme une video ordinaire. Le format, le schéma et le peintre restent tels quels (ADR-0156 §7, ADR-0233).
Quand l'utiliser
Prenez d'abord la route nommée. Lisez la liste des effects dans montagent://schema/index.json : lorsqu'un membre compose le look (flou, ombre, teinte, un blend, un mask avec clé), utilisez-le. Pré-rendez uniquement lorsque aucun membre, peinture ou blend ne compose le look : distorsions, mosaïque, flare d'objectif, particules, motif procédural, ou un modèle/scène 3D externe.
Utilisez la route SVG lorsque vous avez un dessin vectoriel (un logo, une icône, une illustration) en fichier SVG, ou lorsqu'un fixe est plus facile à dessiner en SVG. Aucun élément n'accepte un fichier SVG (ADR-0171). Un SVG qui anime (SMIL ou CSS) n'est pas cette route : il se pixellise en une seule image fixe et le mouvement est perdu. Utilisez plutôt les clés scale, rotation et opacity de l'image placée.
Utilisez la route scène 3D lorsque vous avez un asset 3D (.glb, .gltf, .obj, .fbx, .blend, .c4d) ou une scène 3D. Aucun élément n'accepte un modèle 3D ou un passage multicanal (ADR-0167, ADR-0233). Le rendu sans tête produit des séquences transparentes ProRes 4444 / PNG en dehors du rendu, prêtes pour un placement 2D direct.
Utilisez la route Lottie lorsque vous avez un fichier JSON Lottie (une exportation After Effects, une animation LottieFiles), ou lorsqu'un mouvement est plus facile à tirer d'un tel fichier. Aucun élément n'accepte un fichier Lottie (ADR-0171). Cela coûte trois choses. Une résolution fixe : la séquence est pixellisée à la taille à laquelle vous la rendez. Une chaîne d'outils de recette : un lecteur Lottie installé pour reproduire la pièce (jamais pour rendre le projet). Taille de la séquence : un PNG dans un MOV va d'environ 6 Mo par seconde pour un art lisse à 141 Mo par seconde pour un art bruité, en 1080p et 25 ips, donc rendez à la taille affichée et pas plus grande. Si le mouvement est composé de quelques formes, l'utilisation de clés sur des éléments natifs rect, ellipse et path est plus petite et reste nette.
Une pièce pré-rendue est une séquence fixe. Sa taille, ses ips et sa durée sont définies lors du rendu. Changer le look signifie rendre à nouveau, donc déterminez d'abord la taille, les ips et la durée du brief, et faites correspondre les fps du projet.
Règles communes
Chaque route les lit. Elles sont écrites une fois.
- Taille. Pixellisez ou dessinez à la plus grande taille à laquelle la pièce est jamais affichée, après
fit,scaleet tout zoom clé, sous forme dewidthetheightlittéraux en pixels. Ne la dérivez jamais duviewBoxd'un SVG : unviewBoxdéfinit les proportions du dessin, pas ses pixels, et les outils ne sont pas d'accord sur un fichier sansviewBox. Écrivez la taille dans la recette. Un zoom ultérieur au-delà rééchantillonne un raster, donc relancez la recette plus grande au lieu d'agrandir. - Texte. Polices vendues uniquement, ou texte converti en contours. Jamais une police système : une machine sans elle dessine autre chose. Une police qui ne peut pas être trouvée est un échec de construction, pas un passage ignoré.
usvg, par exemple, enregistre l'absence et ignore le texte, doncbuildlit les valeursfont-familydu SVG par rapport aux fichiers de polices que vous listez dansfonts, et échoue également sur l'avertissement de police du pixelliseur lui-même. - Recette. Copie source, commandes exactes, versions des outils, taille, et un hachage des pixels décodés, pris via la même lecture que celle utilisée par le décodeur. La reconstruction rapporte une correspondance ou la première différence, et ne compare jamais les octets du fichier. La recette indique où elle se trouve.
Les étapes
Exécutez chaque étape, dans l'ordre. La pièce est placée lorsque l'étape 5 réussit.
- Dessiner. Écrivez du code, dans n'importe quel outil, qui produit des images RGBA d'un nombre fixe de
width,heightetframes: transparent là où rien n'est dessiné. Il écrit du RGBA brut sur stdout, ou des fichiers PNGf00000.png,f00001.pnget ainsi de suite dans le dossier nommé parPRERENDER_FRAMES_DIR. Lisez sa taille à partir dePRERENDER_WIDTH,PRERENDER_HEIGHT,PRERENDER_FPSetPRERENDER_FRAMES. Utilisez l'arithmétique entière ou une graine fixe, afin qu'une deuxième exécution dessine les mêmes octets. L'exemple de pièce est le plus petit qui fonctionne. - Spécification. Écrivez une spécification de construction à côté du code :
name,out(le dossier média du projet),width,height,fps,frames,render(l'argv qui exécute votre code),files(chaque fichier dont le code a besoin), etinputde"png"lorsqu'il écrit des PNG. Exécutezpython3 scripts/prerender.py --helppour chaque clé. Ajoutezversionspour toute bibliothèque dont la version change les pixels (une bibliothèque de canevas, un navigateur sans tête). - Construire.
python3 scripts/prerender.py build <spec>. Il exécute le code, encode un<name>.mov, le décode, et échoue sur la première image qui diffère de ce que votre code a dessiné. Lisez sa dernière ligne :N frames, decoded = drawn. - Placer. Ajoutez la séquence au projet comme un élément
videosimple (ci-dessous), ou exécutezpython3 scripts/prerender.py place <project> <placing>, où<placing>est un fichier JSON{"source": "media/<name>.mov"}plus l'un des éléments suivants :id,at,x,y,origin,width,height,fit,track,layer. Il imprime le projet avec l'élément ajouté, donc redirigez cela vers un nouveau fichier. - Vérifier.
validatele projet et corrigez chaque erreur. Ensuite,montagent probela séquence et confirmez qu'elle signale l'alpha (carries: true). Alors seulement,frameune tuile où la pièce est présente et vérifiez que les parties transparentes montrent ce qui se trouve derrière.
{
"frame": {"width": 640, "height": 360}, "fps": 25, "background": "#101418", "duration": 480, "output": "out/pulse.mp4",
"tracks": [
{"name": "prerender", "layer": 10, "elements": [
{"id": "pulse", "type": "video", "start": 0, "end": 480, "source": "media/pulse.mov", "source_start": 0, "source_end": 480, "volume": 0, "x": 320, "y": 180, "origin": "center", "width": 320, "height": 240, "fit": "contain"}
]}
]
}
L'élément est une video ordinaire : clé opacity, scale et position, ajoutez effects et un blend, et placez-le sur une piste comme n'importe quel clip. La séquence n'a pas de son, donc volume est 0. Son end moins start est la longueur de la séquence ; source_end est la même longueur.
La route SVG
Entrée : un fichier SVG, et la taille en pixels des règles communes.
- Vendre les polices que le texte du SVG utilise, avec
montagent fonts vendor, et définissez chaque<text>dans cette famille avec un attributfont-family. Ou convertissez le texte en contours dans votre outil de dessin et n'utilisez aucune police. - Spécification. Écrivez une spécification de construction à côté du SVG avec
"input": "svg":name,out,svg, leswidthetheightlittéraux,render(l'argv du pixelliseur, avec{width},{height}et{out}là où ils vont),files,fontsetversions. Il n'y a pas d'ips et pas de nombre d'images. - Pixelliser.
python3 scripts/prerender.py build <spec>exécute le pixelliseur une fois, en dehors du rendu. Tout outil qui écrit un PNG RGBA fera l'affaire : la ligne de commanderesvg, un navigateur sans tête, Inkscape. Ignorez les polices système et fournissez-lui les polices vendues, comme dans la spécification ci-dessous. Il écrit<name>.pnget sa recette, et échoue en cas de police manquante. - Placer le PNG comme un élément
imagesimple (ci-dessous), ou exécutezpython3 scripts/prerender.py place <project> <placing>avec{"source": "media/<name>.png", "duration": <ms>}plus l'un des éléments suivants :id,at,x,y,origin,width,height,fit,track,layer. - Vérifier. Exécutez
validateet corrigez chaque erreur, puisframeune tuile où l'image est présente et vérifiez que les parties transparentes montrent ce qui se trouve derrière.
La spécification d'exemple, pour l'exemple SVG (formes, un dégradé et du texte défini dans une police vendue), pixellisée à trois fois son viewBox :
{
"name": "mark", "out": "media", "input": "svg", "svg": "sample_art.svg", "width": 480, "height": 270,
"render": ["resvg", "--skip-system-fonts", "--use-font-file", "Inter-Bold.ttf", "-w", "{width}", "-h", "{height}", "sample_art.svg", "{out}"],
"files": ["sample_art.svg"], "fonts": ["Inter-Bold.ttf"],
"versions": {"resvg": ["resvg", "--version"]}
}
Le PNG a des dimensions de pixels intrinsèques, il entre donc comme une image ordinaire, et les règles fit de ADR-0015 s'appliquent comme pour tout PNG : contain avec les proportions propres de la boîte, ou literal. Le placer à sa propre taille, avec fit de contain, est un dessin 1:1. Affichez-le plus grand que la taille à laquelle vous l'avez pixellisé et le raster est rééchantillonné : exécutez à nouveau la recette à la taille plus grande.
{
"frame": {"width": 640, "height": 360}, "fps": 25, "background": "#101418", "duration": 2000, "output": "out/mark.mp4",
"tracks": [
{"name": "art", "layer": 10, "elements": [
{"id": "mark", "type": "image", "start": 0, "end": 2000, "source": "media/mark.png", "x": 320, "y": 180, "origin": "center", "width": 480, "height": 270, "fit": "contain"}
]}
]
}
Exécutez validate. L'image est une image ordinaire : clé opacity, scale et position, ajoutez effects, placez-la sur une piste.
La route Lottie
Entrée : un fichier JSON Lottie, une taille, une ips et une plage d'images. Les propres w, h et fr du Lottie sont des entrées parmi lesquelles choisir, pas des règles : la taille suit les règles communes (la plus grande taille affichée, sous forme de littéraux), et vous écrivez l'ips et le nombre d'images dans la spécification.
- Choisir un lecteur qui peut écrire des images RGBA, et enregistrez son nom et sa version dans
versions. La compétence n'en choisit pas un : le pré-rendu s'exécute une fois en dehors du rendu et les peintres ne voient jamais le lecteur. L'exemple de lecteur est ThorVG viapip install thorvg-python==1.1.3. - Spécification. Écrivez une spécification de construction à côté du Lottie avec
"input": "lottie":name,out,lottie, leswidthetheightlittéraux,fps,frames,render,files,fontsetversions.renderest l'argv du lecteur, avec{width},{height},{frame}et{out}là où ils vont : il dessine une image sous forme de RGBA brut dans{out}.startetstepoptionnels définissent quelle image Lottie correspond à chaque image de la séquence (l'imageieststart + i * step;steppar défaut estfrdu Lottie divisé parfps). Exécutezpython3 scripts/prerender.py --helppour chaque clé. - Construire.
python3 scripts/prerender.py build <spec>lit d'abord le Lottie et le refuse, en nommant chaque cas, s'il utilise une expression, un effet de calque que le lecteur n'est pas enregistré comme dessinant (listez ceux qu'il gère dansallow_effects), ou du texte dont la police n'a ni chemins de glyphes intégrés ni un fichier vendu dansfonts. Un lecteur ignore tout cela sans un son, donc une construction qui continuerait livrerait une animation différente. Il exécute ensuiterenderune fois par image, un nouveau processus à chaque fois, lit le propre rapport du lecteur sur ce qu'il a ignoré (toute ligne disant ignoré, non pris en charge ou non supporté est un échec de construction : traitez-la comme tel), encode un<name>.movcomme le dit le codec, et échoue sur la première image qui diffère de ce que le lecteur a dessiné. - Placer la séquence comme un élément
videosimple, ou avecplacecomme dans les étapes. Exécutezvalidateetmontagent probele MOV : confirmez qu'il signale l'alpha (carries: true). Ensuite,frameune tuile où la pièce est présente et vérifiez que les parties transparentes montrent ce qui se trouve derrière.
Pourquoi un nouveau lecteur par image. Le harnais ne cherche jamais un seul lecteur en avant. ThorVG ignore un changement d'image inférieur à 0.001, donc l'endroit où une recherche atterrit dépend de la recherche précédente, et la recherche de Skottie mute son objet d'animation. Une image dessinée après d'autres peut différer de la même image dessinée en premier, et la reconstruction ne correspondrait pas, donc chaque image a un lecteur vierge.
...
La route stabilisation
Entrée : une source vidéo dans un conteneur avec données de mouvement (.mp4, .mov), une ou plusieurs des : verrouillage d'image de référence (lock), ping-pong (ping_pong), ralentissement (slow_down). Les sorties sont dans media/.
- Spec. Écrivez une spécification avec
"input": "stabilize". Incluezsource(chemin vers le fichier vidéo), et au moins un sélecteur :"lock": <image>pour verrouiller une image de référence (le clip est rogné à cette image),"ping_pong": truepour jouer puis inverser,"slow_down": <facteur>(par exemple2pour moitié vitesse). Une seule spécification par invocation. Exécutezpython3 scripts/stabilize.py --helppour toutes les options. - Stabiliser.
python3 scripts/stabilize.py build <spec>. Il stabilise la source et écrit<name>.movdansmedia/. La sortie a la même durée que la source, sauf sislow_downouping_pongmodifient la durée. - Placer la séquence stabilisée comme un élément
videoordinaire (comme dans les étapes ci-dessus). Utilisezmontagent probepour vérifier l'alpha si pertinent.
Exemple :
{
"input": "stabilize",
"name": "stabilized_clip",
"out": "media",
"source": "source_video.mp4",
"lock": 30,
"ping_pong": true
}
...
La route scène 3D
Entrée : un fichier de scène 3D (.glb, .gltf, .obj, .fbx, .blend, .c4d), une taille, une ips et une durée.
- Choisir un moteur de rendu qui peut produire des images RGBA avec transparence. La compétence ne dicte pas de moteur ; utilisez un outil de votre choix (par exemple, Blender en mode sans tête avec
--render-format PNG). Ajoutez sa version àversions. - Spec. Écrivez une spécification avec
"input": "3d":name,out,3d(chemin vers le fichier 3D),width,height,fps,frames,render(l'argv du moteur, avec des espaces réservés pour la taille et le chemin de sortie),filesetversions. - Rendre.
python3 scripts/prerender.py build <spec>. Le moteur rend chaque image, produisant une séquence transparente (ProRes 4444 pour vidéo, PNG pour fixes). Le codec doit prendre en charge l'alpha ; la construction échoue si le format ne le fait pas. - Placer la séquence comme une
videoordinaire. Vérifiezcarries: trueavecmontagent probe. - Vérifier. Validez le projet et inspectez une image pour confirmer la transparence.
Le codec
Toutes les séquences sont encodées en ProRes 4444 pour la transparence, ou en PNG pour les fixes. Utilisez ffmpeg avec les paramètres appropriés. La spécification inclut le codec dans render si nécessaire.
La recette
Chaque construction produit un fichier de recette dans le dossier media/ avec le même nom de base que la sortie. Il contient :
- source : la copie de tout fichier d'entrée nécessaire à la reconstruction.
- command : la commande exacte de la spécification
render. - tool_versions : les versions enregistrées dans
versions. - size : les
width,height,fps,framesutilisés. - hash : un hachage SHA-256 des pixels décodés de la première image (pour les séquences) ou de l'image unique (pour les fixes). La reconstruction compare ce hachage au hachage des pixels décodés de la sortie reconstruite.
Pour vérifier une recette, exécutez python3 scripts/prerender.py verify <recipe_file>. Il signale MATCH ou MISMATCH avec la première différence.