Rendu Flamenco sans NAS avec une intégration Kitsu (2026)

Rendu Flamenco sans NAS avec une intégration Kitsu (2026)
🧠
Exécutez Flamenco sans stockage partagé en laissant Kitsu piloter le contexte de rendu et les fichiers.

Vous voulez utiliser Flamenco, mais vous ne voulez pas acheter un NAS.

Si vous êtes un artiste solo ou une micro-structure d’animation, c’est une décision parfaitement rationnelle : le stockage partagé peut être coûteux, ajoute de la charge de maintenance et résout des problèmes que vous n’aurez peut-être pas vraiment avant d’avoir essayé de lancer une ferme de rendu.

Flamenco part d’une configuration studio traditionnelle : fichiers partagés, chemins partagés, accès instantané. Sans NAS, cette hypothèse est difficile à contourner. Flamenco n’a pas de notion de contexte de production : il ne sait donc pas quel plan vous voulez rendre, quelle version est approuvée, ni où se trouvent les fichiers de job. Et sans ces informations, il ne peut pas fonctionner en toute sécurité dans un environnement sans NAS.

C’est là qu’intervient Kitsu.

Kitsu sait déjà ce que Flamenco ne sait pas : tâches, plans, versions, approbations. En traitant Kitsu comme un stockage réseau asynchrone, vous pouvez déplacer les données vers le manager Flamenco quand c’est nécessaire, effectuer le rendu, et éviter complètement le stockage partagé “dur”.

Flamenco ne prend pas en charge ce workflow “out of the box”. Pour que cela fonctionne, vous devez créer un type de job Flamenco personnalisé qui récupère le contexte et les fichiers depuis Kitsu, les met en scène localement, et contrôle quand et comment les rendus sont lancés. Cet article vous montre précisément comment faire.

💡
Vous cherchez des exemples qui fonctionnent ?

Vous pouvez trouver le code source complet de l’intégration d’exemple présentée dans ce guide sur notre GitHub :

🔗 https://github.com/cgwire/blog-tutorials/tree/main/flamenco-kitsu-render-farm

Architecture de haut niveau

Notre configuration repose sur une idée simple : Flamenco effectue le rendu, Kitsu fournit la vérité.

Kitsu
  ↑↓ (REST API)
Custom Flamenco Job Type
  ├── Pre-task Python (fetch task data & files)
  ├── Blender render tasks (Flamenco-managed)
  └── Post-task Python (upload renders back to Kitsu)
Flamenco Manager
  ↓
Flamenco Worker(s)

Flamenco fonctionne exactement comme prévu, avec un Manager qui planifie le travail et des Workers qui exécutent les tâches Blender. Ce qui change, c’est la manière dont les jobs sont définis. Au lieu d’indiquer à Flamenco un dossier partagé et d’espérer que chaque machine verra les mêmes fichiers, nous introduisons un type de job Flamenco personnalisé qui comprend les données de production et sait comment communiquer avec Kitsu.

Kitsu se trouve en dehors de la ferme et expose tout via son API REST : plans, tâches, versions et emplacements des fichiers. Lorsqu’un job de rendu est démarré — manuellement ou via une automatisation — le type de job personnalisé interroge Kitsu pour déterminer exactement ce qu’il faut rendre. Par exemple, il peut demander : « Donne-moi la dernière version d’éclairage approuvée pour le plan 020. » Kitsu répond, et cette réponse devient le job de rendu.

Côté Flamenco, le Manager ne sonde pas Kitsu et ne suit pas l’état de production. Il exécute simplement la définition de job qui lui est fournie. Le type de job personnalisé utilise un petit script Python “pre-task” pour récupérer les métadonnées et les fichiers depuis Kitsu, les mettre en scène localement dans un dossier de job, puis les transmettre à des tâches standards de rendu Blender que Flamenco sait gérer efficacement.

Une fois le rendu terminé, une étape “post-task” en Python renvoie les résultats à Kitsu : téléversement des images rendues, création d’une nouvelle version, ou mise à jour du statut de la tâche. À aucun moment les workers n’ont besoin d’un stockage partagé ou d’un accès permanent au même système de fichiers. Chaque worker récupère ce dont il a besoin, rend en local, puis pousse les résultats de manière asynchrone.


1. Créer un nouveau type de job

Un type de job Flamenco définit comment un job devient un travail concret. C’est la couche de traduction entre « je veux rendre ça » et les tâches concrètes que Flamenco planifie à travers la ferme. Conceptuellement, un type de job déclare les informations dont il a besoin et comment compiler ces informations en tâches.

Le plus simplement possible, un type de job décrit une étiquette et un ensemble de réglages, puis fournit une fonction qui reçoit ces réglages et construit le job. En code, cela ressemble à ceci :

const JOB_TYPE = {
  label: "Kitsu Render",
  settings: [
    // { key: "message", type: "string", required: true },
    // { key: "sleep_duration_seconds", type: "int32", default: 1 },
  ],
};

function compileJob(job) { const settings = job.settings; }

Ce code définit le squelette d’un type de job Flamenco personnalisé. L’objet JOB_TYPE décrit comment le job apparaît dans Flamenco : son libellé lisible par les humains et les paramètres qu’il attend lorsqu’un job est créé.

Ces réglages agissent comme des entrées typées, avec validation gérée par Flamenco : dans cet exemple, une chaîne requise et un entier optionnel avec une valeur par défaut.

La fonction compileJob est l’endroit où le job est transformé en tâches exécutables ; elle reçoit le job soumis, lit les réglages résolus, et les utiliserait normalement pour générer les étapes de rendu, “pre-task” et “post-task”. Telle qu’elle est écrite, la fonction ne fait encore aucun travail, mais elle définit le point d’entrée où la logique de production vivra.

En production réelle, au lieu d’un message générique, vous passez un identifiant de tâche Kitsu, un nom de plan, l’emplacement de sortie souhaité, ou même la version de Blender à utiliser.

L’endroit où vit cette logique a de l’importance. Les types de job Flamenco personnalisés tournent sur le Flamenco Manager, pas sur les workers. Sur disque, ils se trouvent à côté du programme du manager, par exemple :

$ flamenco
└── flamenco-manager
└── scripts/
└── kitsu-render.js

En pratique, les studios considèrent ces scripts de types de job comme faisant partie de leur base de code de pipeline. Ils sont suivis en contrôle de version, évoluent au fil du temps et sont déployés avec les mises à jour de Flamenco. Ainsi, vous pouvez modifier la manière dont les jobs sont construits et comment Kitsu est interrogé sans redéployer ni reconfigurer chaque machine worker de la ferme.

Pour les scripts worker appelés par les types de job personnalisés en tant que commandes, nous les plaçons à côté de notre programme flamenco-worker :

$ flamenco
└── flamenco-worker
└── kitsu-render.py

2. Ajouter des tâches

Dans compileJob, vous définissez explicitement les tâches qui composent le job. C’est ici que la demande de haut niveau « rendre ce plan » se transforme en travail concret, planifiable, que Flamenco peut confier aux workers.

L’exemple ci-dessous montre la tâche la plus simple possible. Une tâche echo est créée via l’API d’édition de tâches de Flamenco, fournie avec une catégorie, puis assignée à une seule commande. Cette commande passe le réglage de job résolu dans la tâche, qui imprimera simplement le message lorsqu’elle s’exécutera. Enfin, la tâche est ajoutée au job pour que le Manager puisse la planifier.

const echoTask = author.Task("echo", "misc");
echoTask.addCommand(
author.Command("echo", {
message: settings.message,
}),
);
job.addTask(echoTask);

Même si cette tâche ne fait rien d’utile par elle-même, le pattern est la partie importante. Le même mécanisme sert à exécuter des scripts Python, à lancer Blender en mode “arrière-plan” pour le rendu, ou à effectuer des contrôles de validation avant qu’une tâche soit considérée comme terminée. Chaque tâche est conçue pour être atomique et redémarrable : cela signifie qu’en cas de crash d’un worker ou d’échec d’un rendu à 3 h du matin, Flamenco peut réessayer uniquement cette tâche sans compromettre l’ensemble du job. Cette fiabilité permet à cette approche de passer à l’échelle quand vous exécutez des centaines de plans pendant la nuit.

Passons maintenant à la partie la plus “dense” du tutoriel : coder une tâche qui télécharge des assets depuis Kitsu, rend avec Blender, puis re-téléverse le résultat vers Kitsu.


3. Sous-commande 1 : Télécharger des assets depuis Kitsu

La première vraie tâche de notre job piloté par Kitsu consiste à récupérer exactement les données dont nous avons besoin depuis Kitsu et à préparer un espace de travail local propre sur le worker. Avant même que Blender démarre, le worker doit savoir quelle tâche il rend et où se trouvent les fichiers du job.

Au lieu d’écrire la logique en Javascript, nous utilisons le bien plus simple SDK Python gazu pour créer un script kitsu-render, puis l’appelons depuis Javascript. Si vous n’avez pas Python installé dans l’environnement de votre worker, envisagez de créer un binaire exécutable à partir du script Python.

function compileJob(job) {
const settings = job.settings;

const task = author.Task("kitsu-render", "misc");

task.addCommand( author.Command("exec", { exe: "python3", args: "kitsu-render.py" }), );

job.addTask(task); }

Le script Python s’authentifie auprès de l’API Kitsu, recherche des tâches de rendu TODO, puis télécharge le fichier de preview associé contenant un projet .blend à rendre.

import os
import gazu

gazu.set_host("http://localhost/api") user = gazu.log_in("admin@example.com", "mysecretpassword")

projects = gazu.project.all_projects() project = projects0

tasks = gazu.task.all_tasks_for_project(project)

rendering = gazu.task.get_task_type_by_name("Rendering") todo = gazu.task.get_task_status_by_name("todo")

render_tasks = t for t in tasks if t"task_type_id" == rendering"id" and t"task_status_id" == todo"id"

for task in render_tasks: files = gazu.files.get_all_preview_files_for_task(task) if not files: continue

latest = files[-1]
if latest["extension"] == "blend":
    task_to_render = task
    latest_blend = latest
    break

if task_to_render is None: raise RuntimeError("No render task with a .blend preview found")

target_path = os.path.join( "/tmp", latest_blend"original_name" + "." + latest_blend"extension" )

gazu.files.download_preview_file(latest_blend, target_path)

Cette étape rend un workflow sans NAS viable. Chaque worker récupère uniquement les fichiers dont il a besoin pour la tâche spécifique qu’il exécute, au lieu de monter ou synchroniser un arbre de production complet. Si le téléchargement échoue, Flamenco peut réessayer automatiquement la tâche sans intervention humaine.


4. Sous-commande 2 : Rendu Blender

Une fois le fichier blend à rendre préparé localement sur le worker, nous pouvons le rendre de façon programmatique avec la bibliothèque bpy :

bpy.ops.wm.open_mainfile(filepath=target_path)

output_path = os.path.join( "/tmp", latest_blend"name" + ".mp4" )

bpy.context.scene.render.image_settings.file_format = "FFMPEG" bpy.context.scene.render.ffmpeg.format = "MPEG4" bpy.context.scene.render.ffmpeg.codec = "H264" bpy.context.scene.render.ffmpeg.constant_rate_factor = "HIGH" bpy.context.scene.render.ffmpeg.gopsize = 12 bpy.context.scene.render.ffmpeg.audio_codec = "AAC" bpy.context.scene.render.filepath = output_path

bpy.ops.render.render(animation=True)

Un pipeline plus avancé exploiterait la commande native “blender-render” de Flamenco pour découper automatiquement la plage de frames en unités de travail plus petites et les distribuer sur les workers disponibles. Si une machine tombe ou qu’une frame échoue, seules ces frames sont relancées : il n’est donc pas nécessaire de redémarrer tout le plan, ni de construire une logique de file d’attente personnalisée pour gérer le parallélisme.

Mais pour garder notre exemple simple, nous rendons simplement toute la vidéo sur un seul worker.


5. Sous-commande 3 : Téléverser les résultats vers Kitsu

La dernière étape du job est une sous-commande “post-render” qui renvoie les résultats de rendu vers Kitsu. À ce stade, le worker a terminé sa plage de frames en local, et la responsabilité de la ferme passe du calcul à la publication. C’est là que la sortie rendue devient visible pour le reste de la production.

L’exemple ci-dessous montre une instruction Python minimale qui téléverse le fichier vidéo résultant dans Kitsu en tant que pièce jointe sur la tâche d’origine.

result = gazu.task.publish_preview(
task_to_render,
todo,
comment="rendered",
preview_file_path=output_path,
)

Dans un pipeline de production réel, cette étape fait généralement plus que simplement téléverser des fichiers. Nous pouvons créer une nouvelle version dans Kitsu, mettre à jour le statut de la tâche à quelque chose comme Done, et déclencher des workflows de review ou de notification afin que les superviseurs sachent que la nouvelle sortie est prête. Comme cette logique est simplement du Python exécuté à l’intérieur d’une tâche Flamenco, il est facile d’évoluer à mesure que les besoins de production changent, sans toucher à la ferme de rendu elle-même.


6. Déclencher le workflow

Une fois le type de job personnalisé en place, le workflow est déclenché en soumettant une demande de job au Flamenco Manager. Pendant le développement, cela se fait souvent manuellement en appelant directement l’API REST du Manager. C’est une façon rapide de valider que la compilation du job fonctionne, que les réglages sont correctement câblés, et que les tâches se comportent comme prévu avant d’ajouter une couche d’automatisation.

L’exemple ci-dessous soumet un job de type kitsu-render au Manager. Avec, en plus, des métadonnées de base pour le suivi et l’attribution, la requête inclut une valeur de priorité et un objet settings vide, qui contiendrait normalement des entrées propres à la production, comme un ID de production Kitsu. Lorsque le job est accepté, le Manager invoque le type de job personnalisé, compile les tâches et les planifie sur les workers disponibles.

curl -X 'POST' 
'http://172.17.0.1:8080/api/v3/jobs'
-H 'accept: application/json'
-H 'Content-Type: application/json'
-d '{ "metadata": { "project": "kitsu", "user.email": "basunako@gmail.com", "user.name": "kitsu" }, "name": "Kitsu Render", "priority": 50, "settings": {}, "submitter_platform": "linux", "type": "kitsu-render" }'

Nous pouvons voir que le manager a bien reçu la demande de job et l’a assignée à un worker :

Ce déclenchement manuel est principalement un outil de développement. Il vous permet d’itérer sur la logique des jobs, de tester des cas limites et de relancer des jobs sans impliquer les artistes ni les outils de production.

En production, les studios automatisent toujours cette étape. Un petit service (souvent un cron ou un listener webhook léger) interroge périodiquement Kitsu pour trouver des tâches prêtes à être rendues, comme des plans nouvellement approuvés ou publiés. Lorsqu’il en trouve une, il soumet un job correspondant au Flamenco Manager en utilisant le même appel API.

Une fois cela en place, Flamenco devient un backend de rendu conscient de la production, plutôt que d’attendre que des humains appuient sur des boutons : il réagit automatiquement aux changements dans Kitsu et garde la ferme synchronisée avec l’état de la production.


Conclusion

Ce que vous avez construit dans cet article est une manière fondamentalement différente de penser le rendu dans les petits studios.

En utilisant un type de job Flamenco personnalisé pour récupérer du contexte et des données depuis Kitsu, mettre en scène le travail en local, rendre via le planificateur natif de Flamenco, puis renvoyer les résultats de façon asynchrone, vous avez supprimé le besoin de stockage partagé sans sacrifier la fiabilité ni la capacité de montée en charge.

Chaque élément a une responsabilité claire : Kitsu définit ce qui est vrai en production, Flamenco décide comment le travail s’exécute, et votre type de job personnalisé fait l’interface qui les maintient synchronisés. Cette séparation rend le système robuste, débogable et adaptable à mesure que votre pipeline grandit.

Comprendre ce pattern est important, car cela vous permet de construire une infrastructure de rendu qui correspond à la réalité des artistes solo et des micro-studios.

Mais ne vous arrêtez pas là : cliquez sur le dépôt GitHub de notre exemple pour cet article et commencez à rendre dès aujourd’hui !

📽️
Pour en savoir plus sur le processus d’animation envisagez de rejoindre notre communauté Discord ! Nous échangeons avec plus d’un millier d’experts qui partagent leurs bonnes pratiques et organisent parfois des événements en présentiel. Nous serions ravis de vous accueillir ! 😊

Vous appréciez cet article ?

Abonnez-vous à notre newsletter pour plus d'analyses, de tutoriels et d'actualités du secteur.