Comment générer automatiquement des plans Blender avec Python et Kitsu (2026)

Comment générer automatiquement des plans Blender avec Python et Kitsu (2026)
🧩
Automatisez la préparation de vos plans et éliminez des heures de placement manuel d’assets.

Les studios d’animation s’appuient sur des listes de breakdown pour suivre les assets qui doivent apparaître dans chaque plan.

Imaginez ceci. Vous êtes un(e) artiste VFX, face à un viewport Blender vide pour la production en cours. Votre responsable vous remet la liste détaillée des assets, des plans et des repères de timing, puis vous dit : "Transforme ça en scène Blender."

Votre première idée pourrait être de vous connecter à votre gestionnaire d’assets et de placer chaque objet manuellement. Mais qu’en est-il des scènes complexes avec des centaines d’assets ?

C’est à ce moment qu’une simple automatisation peut sauver la mise. Avec le scripting Python pour Blender, vous pouvez lire les données de breakdown de Kitsu et générer automatiquement une scène initiale en quelques minutes.

Dans cet article, nous allons parcourir un exemple complet : récupérer des breakdowns via la API Python de Gazu, créer une nouvelle scène Blender, télécharger les assets, et les importer dans Blender. À la fin, vous disposerez d’un pipeline minimal qui construit des scènes automatiquement, prêtes pour le layout ou l’animation.

💡
Vous cherchez des exemples fonctionnels ?

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

🔗 https://github.com/cgwire/blender-kitsu-automated-scene-composition

1. Obtenir le breakdown

Chaque plan 3D commence comme une toile vierge, mais les instructions pour remplir cette toile existent déjà dans Kitsu : le breakdown indique précisément ce qui doit se trouver sur scène avant que l’animateur commence son travail.

Un breakdown typique fournit le contexte narratif essentiel dont votre script a besoin pour assembler la scène : la scène (images de départ et de fin, durée et autres annotations stockées dans les informations de séquence), et la distribution (le breakdown réel des modèles de personnages, des props et des assets d’environnement).

Avant d’écrire du code, vous devez définir le breakdown dans le tableau de bord Kitsu. C’est là que vous reliez manuellement votre bibliothèque d’assets 3D aux plans spécifiques pour lesquels ils sont requis. Ici, vous ne créez pas de nouveaux modèles : vous affectez simplement des « acteurs » (assets) à un plan précis :

  1. Accédez à votre production - Naviguez vers votre projet dans Kitsu et ouvrez l’onglet Shots.
  2. Trouvez la feuille de casting - Cherchez l’onglet Breakdown (généralement situé dans le panneau de droite ou dans un onglet dédié selon votre version).
  3. Sélectionnez le plan - Cliquez sur le plan précis que vous souhaitez remplir (par ex. SH01) pour ouvrir la vue détaillée du casting.
  4. Assignez les assets - Dans le panneau latéral droit, cliquez sur le bouton + (Plus) ou sur « Add Asset ». Vous pouvez aussi indiquer ici la quantité de chaque asset dont vous avez besoin.

Assurez-vous que votre page Assets contient déjà les modèles (Characters, Props, etc.) que vous avez l’intention d’utiliser.

Une fois que vous cliquez sur enregistrer, le lien est établi. Maintenant, lorsque votre script Python demande à Gazu : « Qui est dans ce plan ? », Kitsu répond avec la liste des assets que vous venez d’assigner. Votre script Python joue le rôle de passerelle : il analyse ce casting pour remplir automatiquement le viewport Blender.

Si vous avez besoin d’un environnement local de développement, jetez un œil à comment installer Kitsu depuis Docker dans le guide Custom DCC Bridge.

Pendant que Kitsu détient les données, nous avons besoin d’un moyen de les récupérer. Passons à Gazu, le SDK Python pour l’API REST de Kitsu :

import gazu

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

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

sequence = gazu.shot.get_sequence_by_name(project, "SQ01") shot = gazu.shot.get_shot_by_name(sequence, "SH01")

assets = gazu.casting.get_shot_casting(shot)


On se connecte à notre instance locale de Kitsu, puis on choisit notre première production (vous pouvez aussi récupérer une production par nom) et le plan pour lequel nous avons besoin du casting.

Nous pouvons utiliser cet identifiant de plan pour récupérer le casting correspondant des assets, c’est-à-dire la liste de breakdown.


2. Obtenir des assets à partir d’un breakdown

Maintenant que nous savons qui se trouve dans le plan, nous devons déterminer à quoi ils ressemblent.

Dans Kitsu, un asset peut avoir de nombreux fichiers d’aperçu que nous pouvons utiliser selon les révisions. Notre script doit pouvoir parcourir ces données pour obtenir la dernière révision de chaque asset :

local_paths = 
for asset in assets:
    tasks = gazu.task.all_tasks_for_asset(asset"asset_id")
    last_task = max(tasks, key=lambda x: x"updated_at")

    preview_files = gazu.files.get_all_preview_files_for_task(last_task)     last_preview_file = max(preview_files, key=lambda x: x"updated_at")

    download_dir = "./previews"     os.makedirs(download_dir, exist_ok=True)

    save_path = os.path.join(         download_dir,         last_preview_file"original_name" + "." + last_preview_file"extension",     )

    gazu.files.download_preview_file(last_preview_file, save_path)

    local_paths.append(save_path)


Pour chaque asset, nous récupérons une liste de toutes les tasks correspondantes, quel que soit le type (« Modeling », « Animation », etc.) ou le statut (« done », « todo »…). Nous filtrons cette liste pour obtenir la task mise à jour le plus récemment.

Nous pouvons utiliser l’identifiant de cette task pour obtenir la dernière révision du fichier d’aperçu correspondant et le télécharger dans un dossier local previews. Nous conservons ces chemins de téléchargement en mémoire pour l’étape d’import.

À la fin de cette boucle, vous avez transformé avec succès des entrées de base de données en fichiers modèles concrets sur votre disque dur, prêts à être importés par Blender.


3. Créer une nouvelle scène Blender

Une fois les fichiers d’assets téléchargés en toute sécurité, la tâche suivante consiste à préparer l’environnement Blender afin d’accueillir son nouveau membre de distribution.

Le module bpy, l’API Python native de Blender, agit comme votre console de commandes et vous permet de manipuler chaque élément de l’application.

Avant d’importer nos assets Kitsu, nous devons supprimer tous les objets par défaut qui accompagnent une nouvelle scène Blender. Pour ce tutoriel simple, nous visons le Cube par défaut, souvent le seul objet présent en dehors de la Camera et de la Light :

bpy.data.objects.remove(bpy.data.objects.get("Cube"), do_unlink=True)


Le paramètre do_unlink=True indique à Blender de supprimer complètement le bloc de données de l’objet (comme ses données de maillage) s’il n’est plus utilisé par un autre objet, afin de ne laisser aucun élément superflu.

Nous sommes maintenant prêts à placer les assets importés à leur position.


4. Importer des fichiers d’assets

Passons au résultat ! Le fichier que nous avons téléchargé depuis Kitsu est un format d’échange standardisé .glb, qui gère à la fois la géométrie et les matériaux de base ; nous utilisons donc l’opérateur d’import dédié gltf de Blender.

La partie cruciale est de fournir le chemin de fichier absolu (glb_path) vers l’asset téléchargé. Heureusement, nous les avons stockés dans l’extrait de code précédent :

for path in local_paths:
    if path.lower().endswith((".glb")):
        print(f"Importing: {path}")
        bpy.ops.import_scene.gltf(filepath=path)

print("All preview GLB files imported successfully!")


Une fois que bpy.ops.import_scene.gltf() s’exécute, Blender lit le fichier et crée automatiquement les objets, meshes et materials correspondants dans la scène en cours.

L’asset importé est désormais un objet Blender à part entière, placé à l’origine du monde (0, 0, 0), prêt pour les étapes suivantes du pipeline.


5. Enregistrer la scène

La dernière étape dans ce segment de pipeline est d’enregistrer la mise en page assemblée dans un fichier permanent et versionnable. Si vous fermez Blender sans cette étape, tout le travail automatisé est perdu : nous utilisons donc l’opérateur bpy.ops.wm.save_as_mainfile. C’est l’équivalent programmatique du clic File &gt; Save As dans l’interface Blender :

scene_save_dir = "./"
os.makedirs(scene_save_dir, exist_ok=True)

blend_filename = "SH01.blend" blend_path = os.path.join(scene_save_dir, blend_filename)

bpy.ops.wm.save_as_mainfile(filepath=blend_path)


Le résultat est un nouveau fichier Blender, SH01.blend, qui reflète parfaitement les exigences de breakdown depuis Kitsu, prêt pour que le prochain département puisse le récupérer.


6. Un addon convivial

Le script fonctionne comme prévu, mais qu’en est-il des artistes ? Tout le monde ne sait pas comment exécuter un script.

Modifions légèrement notre code pour le transformer en addon Blender :

bl_info = {
    "name": "Kitsu Shot Auto-Importer",
    "description": "Pick a project and shot and auto-import the latest preview assets",
    "author": "cgwire",
    "version": (1, 0, 0),
    "blender": (3, 0, 0),
    "location": "Viewport > N-Panel > Kitsu",
    "category": "Import-Export",
}

import os import sys

sys.path.append("~/.local/lib/python3.11/site-packages")

import bpy import gazu from bpy.props import EnumProperty, StringProperty

def get_projects():     try:         projects = gazu.project.all_projects()         return (p"id", p"name", "") for p in projects     except:         return

def get_sequences(project_id):     if not project_id:         return     try:         seqs = gazu.shot.all_sequences_for_project(project_id)         return (s"id", s"name", "") for s in seqs     except:         return

def get_shots(sequence_id):     if not sequence_id:         return     try:         shots = gazu.shot.all_shots_for_sequence(sequence_id)         return (s"id", s"name", "") for s in shots     except:         return

class KITSU_Props(bpy.types.PropertyGroup):     project: EnumProperty(name="Project", items=lambda self, context: get_projects())

    sequence: EnumProperty(         name="Sequence", items=lambda self, context: get_sequences(self.project)     )

    shot: EnumProperty(         name="Shot", items=lambda self, context: get_shots(self.sequence)     )

class KITSU_OT_import_shot(bpy.types.Operator):     bl_idname = "kitsu.import_shot_assets"     bl_label = "Import Shot Assets"     bl_description = (         "Download and import latest preview GLB/GLTF files for selected shot"     )

    def execute(self, context):         props = context.scene.kitsu_props

        # Fetch shot data         shot = gazu.shot.get_shot(props.shot)         assets = gazu.casting.get_shot_casting(shot)

        download_dir = os.path.join(bpy.app.tempdir, "kitsu_previews")         os.makedirs(download_dir, exist_ok=True)

        local_paths =

        for asset in assets:             tasks = gazu.task.all_tasks_for_asset(asset"asset_id")             if not tasks:                 continue

            last_task = max(tasks, key=lambda x: x"updated_at")             preview_files = gazu.files.get_all_preview_files_for_task(last_task)             if not preview_files:                 continue

            last_preview = max(preview_files, key=lambda x: x"updated_at")

            save_path = os.path.join(                 download_dir,                 last_preview"original_name" + "." + last_preview"extension",             )

            gazu.files.download_preview_file(last_preview, save_path)             local_paths.append(save_path)

        # Clean default cube         obj = bpy.data.objects.get("Cube")         if obj:             bpy.data.objects.remove(obj, do_unlink=True)

        # Import GLB/GLTF assets         for path in local_paths:             if path.lower().endswith((".glb", ".gltf")):                 bpy.ops.import_scene.gltf(filepath=path)

        # Auto-save blend file         save_dir = os.path.join(os.path.expanduser("~"), "kitsu_scenes")         os.makedirs(save_dir, exist_ok=True)

        blend_path = os.path.join(save_dir, f"{shot'name'}.blend")         bpy.ops.wm.save_as_mainfile(filepath=blend_path)

        self.report({"INFO"}, f"Imported assets and saved: {blend_path}")         return {"FINISHED"}

class KITSU_PT_panel(bpy.types.Panel):     bl_label = "Kitsu Auto-Importer"     bl_idname = "KITSU_PT_auto_importer"     bl_space_type = "VIEW_3D"     bl_region_type = "UI"     bl_category = "Kitsu"

    def draw(self, context):         props = context.scene.kitsu_props         layout = self.layout

        layout.separator()         layout.prop(props, "project")         layout.prop(props, "sequence")         layout.prop(props, "shot")

        layout.separator()         layout.operator("kitsu.import_shot_assets", icon="IMPORT")

classes = (     KITSU_Props,     KITSU_OT_import_shot,     KITSU_PT_panel, )

def register():     for c in classes:         bpy.utils.register_class(c)     bpy.types.Scene.kitsu_props = bpy.props.PointerProperty(type=KITSU_Props)

def unregister():     for c in classes:         bpy.utils.unregister_class(c)     del bpy.types.Scene.kitsu_props

if name == "main":     register()


Vous pouvez maintenant choisir manuellement une production, une séquence et un plan pour récupérer les données de breakdown, puis importer le casting correspondant dans le viewport Blender actuel :

La logique est simple : on utilise le même code gazu pour alimenter les menus déroulants, et on encapsule tout cela dans un panneau de la vue. Un bouton import télécharge tous les assets de breakdown correspondants et les importe dans l’espace de travail actuel.

N’oubliez pas que l’ajout de sys.path.append("~/.local/lib/python3.11/site-packages") permet à Blender d’utiliser l’installation Python de votre système pour charger des bibliothèques externes comme gazu. Comme Blender est fourni avec son propre environnement Python isolé, gérer l’installation des packages peut être contraignant. En étendant le chemin, vous indiquez simplement à Blender de vérifier aussi vos modules locaux. Assurez-vous d’ajuster ce chemin pour qu’il corresponde à votre configuration.


Conclusion

En récupérant directement les listes de breakdown depuis Kitsu et en scriptant Blender pour assembler des scènes, vous éliminez les étapes manuelles répétitives et vous garantissez la cohérence des assets sur tous les plans. Cette approche ne fait pas que gagner du temps : elle réduit aussi les erreurs humaines et garantit que chaque artiste démarre avec la bonne version d’assets et la configuration de scène requise par le producteur. Ainsi, vous pouvez gérer facilement dix plans ou dix mille, avec la même fiabilité.

Mais ne nous croyez pas sur parole, cloniez le dépôt GitHub pour tester le résultat !

Vous pouvez étendre ce workflow en générant des aperçus automatisés, des rapports, ou même en mettant à jour les informations d’assets à partir des nouvelles révisions créées pendant l’animation du plan.

📽️
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 les meilleures 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.