Automatiser des rapports Kitsu avec Python et Gazu (2026)

Automatiser des rapports Kitsu avec Python et Gazu (2026)
📊
Transformez des heures de reporting manuel en un PDF Kitsu entièrement automatisé en quelques secondes.

Combien d’heures passez-vous chaque semaine à récupérer des données et à générer des rapports ?

Les studios d’animation utilisent Kitsu pour suivre l’avancement, mais nous voyons encore des superviseurs passer des heures à compiler manuellement ces données en PDF, juste pour tenir les producteurs et réalisateurs informés. C’est un énorme drain d’énergie créative, et un point de défaillance manuel que l’équipe senior ne devrait pas avoir à gérer. Si les données existent déjà dans notre logiciel de suivi, les partager ne devrait pas être une galère.

En tant que lead technique, votre mission est d’automatiser les tâches fastidieuses afin que les artistes puissent se concentrer sur l’art. Et en utilisant le client Python de Gazu, nous pouvons combler l’écart entre la base de données de Kitsu et le rapport final destiné aux parties prenantes.

Aujourd’hui, nous allons créer un script qui récupère automatiquement des indicateurs de projet et génère un PDF personnalisé, transformant une tâche manuelle de 2 heures en un travail automatisé de 5 secondes.


Pourquoi des rapports personnalisés ?

Kitsu est une bouée de sauvetage pour garder l’organisation du chaos de la production. Le tableau de bord intégré couvre tous les cas d’usage, y compris l’analyse multi-production. Mais parfois, « standard » ne suffit pas.

Par exemple, les clients voudront peut-être avoir l’impression qu’ils paient pour un service premium. Leur envoyer une capture brute du logiciel ou un lien générique peut donner une impression un peu amateur. En utilisant des rapports personnalisés, vous pouvez fournir des mises à jour d’avancement encapsulées dans le branding de votre studio, ce qui garantit une présentation aussi soignée que les images que vous livrez.

Il y a ensuite la difficulté de trouver un format qui conviendra au producteur. Le producteur demande un tableau croisé Excel très spécifique ou un PDF hérité pour les archives, qui suit une logique interne étrange, compréhensible uniquement par lui. Si vous devez exporter une liste filtrée de chaque plan de la Séquence 02 qui est actuellement « En cours » mais bloqué par des retakes « En retard », un rapport personnalisé vous fournit ces données instantanément. Cela vous évite le cauchemar du copier-coller manuel et vous permet de revenir à l’animation.

Certains studios ont aussi besoin de vues personnalisées pour un suivi avancé. Des données sur mesure peuvent vous aider à repérer des goulots d’étranglement par département : par exemple, quand l’équipe d’éclairage est constamment en pause parce que le cache FX accuse du retard. Vous pouvez ainsi résoudre la friction avant qu’elle ne se transforme en rush de fin de semaine.

Heureusement, Kitsu est très simple à étendre.

💡
Vous cherchez des exemples concrets ?

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

🔗 https://github.com/cgwire/blog-tutorials/tree/main/custom-kitsu-reports

1. Configuration Kitsu & authentification

Tout d’abord, vous devez parler à votre instance Kitsu.

Si vous n’avez pas encore d’URL de studio et que vous souhaitez lancer Kitsu sur votre propre machine, Docker est le moyen le plus rapide pour mettre en place un environnement prêt pour la production :

docker run --init -ti --rm -p 80:80 -p 1080:1080 --name cgwire cgwire/cgwire

Pour le scripting, nous utiliserons le SDK Python officiel de Kitsu, gazu.

Vous pouvez vous authentifier avec vos identifiants utilisateur, ce qui convient très bien aux tests locaux :

import gazu

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


2. Récupérer les données de production

Avant d’écrire la moindre ligne de code, nous devons parler des données que Kitsu expose. Si elles existent dans l’interface, vous pouvez probablement les récupérer via Gazu.

L’API est étonnamment riche. Pour un rapport de production solide, vous pourriez généralement récupérer :

  • Indicateurs d’avancement : changements de statut (par exemple, passer de « WIP » à « Review interne » via des événements).
  • Suivi du temps : la durée d’un plan « En cours » par rapport à l’estimation initiale.
  • Listes d’interprétation : chaque personnage, environnement et accessoire associé à un épisode ou une séquence donnée.
  • Charge de travail : le nombre exact de frames ou d’assets actuellement assignés à un artiste spécifique.
  • Budget : l’évolution de la quota de l’équipe dans le temps.
  • Et bien d’autres ressources à découvrir dans notre documentation développeur détaillée.

Regardons un scénario courant : vous devez obtenir rapidement un récapitulatif de toutes les tâches actuellement assignées à vos membres d’équipe pour un projet donné. C’est la base de tout rapport « Qui fait quoi ? ».

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

tasks = gazu.task.all_tasks_for_project(project)

report =

for task in tasks: assignees = gazu.person.get_person(p_id)"full_name" for p_id in task"assignees"

task_info = {
    "date": task["updated_at"],
    "entity": gazu.entity.get_entity(task["entity_id"])["name"],
    "type": gazu.task.get_task_type(task["task_type_id"])["name"],
    "status": gazu.task.get_task_status(task["task_status_id"])["name"]
}

for artist in assignees:
    report.append({**task_info, "artist": artist})

Gazu renvoie des dictionnaires. Lorsque vous récupérez all_tasks_for_project, gardez à l’esprit qu’en production long métrage, cela peut représenter une quantité massive de données. Essayez toujours de filtrer vos données. Par exemple, par task_status ou entity_type, si vous ne devez voir que des plans d’Animation actifs, par exemple.


3. Créer un modèle réutilisable

Ensuite, vous devez décider comment générer le PDF. Il existe deux options principales.

Vous pouvez utiliser ReportLab. C’est la méthode la plus directe. C’est rapide et ne nécessite aucune dépendance externe non-Python. Idéal pour des rapports techniques internes, des tableaux simples, et de l’automatisation par lots très rapide.

Ou vous pouvez créer une chaîne de rendu HTML vers PDF en utilisant Jinja2 (gabarits) et WeasyPrint. C’est souvent la méthode préférée, car vous pouvez utiliser le CSS pour styliser le rapport. Si vous pouvez créer une page web, vous pouvez créer un rapport. C’est le mieux pour les livrables destinés aux clients, le branding important, et les mises en page complexes.

Définissons votre configuration et votre modèle :

STUDIO_NAME = "My Animation Studio"
STUDIO_LOGO = "studio_logo.png"  # chemin de fichier local
PROJECT_NAME = "My Project"
OUTPUT_PDF = "activity_report.pdf"

Vous utilisez la syntaxe Jinja2 () pour injecter vos données Python dans du HTML standard.

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
}
header {
display: flex;
align-items: center;
margin-bottom: 30px;
}
header img {
height: 50px;
margin-right: 20px;
}
h1 {
color: #2a2a2a;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th {
background: #222;
color: white;
padding: 8px;
text-align: left;
}
td {
padding: 8px;
border-bottom: 1px solid #ccc;
}
.footer {
margin-top: 40px;
font-size: 10px;
color: #777;
text-align: center;
}
</style>
</head>
&lt;body&gt;
    &lt;header&gt;
        &lt;img src="{{ studio_logo }}" /&gt;
        &lt;h1&gt;{{ studio_name }} – Activity Report&lt;/h1&gt;
    &lt;/header&gt;

    &lt;p&gt;
        &lt;strong&gt;Project:&lt;/strong&gt; {{ project_name }}&lt;br /&gt;
        &lt;strong&gt;Report Date:&lt;/strong&gt; {{ report_date }}
    &lt;/p&gt;

    &lt;table&gt;
        &lt;tr&gt;
            &lt;th&gt;Date&lt;/th&gt;
            &lt;th&gt;Artist&lt;/th&gt;
            &lt;th&gt;Task&lt;/th&gt;
            &lt;th&gt;Entity&lt;/th&gt;
            &lt;th&gt;Status&lt;/th&gt;
        &lt;/tr&gt;
        {% for row in rows %}
        &lt;tr&gt;
            &lt;td&gt;{{ row.date }}&lt;/td&gt;
            &lt;td&gt;{{ row.artist }}&lt;/td&gt;
            &lt;td&gt;{{ row.entity }}&lt;/td&gt;
            &lt;td&gt;{{ row.type }}&lt;/td&gt;
            &lt;td&gt;{{ row.status }}&lt;/td&gt;
        &lt;/tr&gt;
        {% endfor %}
    &lt;/table&gt;

    &lt;div class="footer"&gt;Generated automatically by {{ studio_name }}&lt;/div&gt;
&lt;/body&gt;

</html>

Ce fichier HTML agit comme un modèle Jinja2 qui définit la structure visuelle et le style du rapport, y compris la mise en page, les polices, les couleurs et un tableau pour afficher les données d’activité. Les expressions null marquent des emplacements pour des valeurs comme le nom du studio, l’URL du logo, le nom du projet et la date du rapport, tandis que le CSS intégré garantit que le document a un rendu soigné et prêt à imprimer une fois rendu ou converti en PDF.

Lorsque le code Python rend ce modèle, Jinja2 remplace tous les emplacements par les valeurs réelles transmises depuis le script et exécute la boucle {% for row in rows %} pour générer une ligne de tableau par enregistrement d’activité. Chaque dictionnaire row fournit la date, l’artiste, la tâche, l’entité, le statut et les valeurs d’heures, avec le champ des heures explicitement formaté à deux décimales, ce qui produit un document HTML complet avec un tableau entièrement rempli.

Le HTML rendu est donné à WeasyPrint, qui interprète à la fois la structure HTML et le CSS en ligne pour disposer le contenu comme un document imprimable. Le logo du studio est chargé via son URL ou un chemin relatif, le tableau et le texte sont stylisés exactement comme défini dans le modèle, et tout est rendu dans un fichier PDF qui correspond visuellement à la maquette HTML, en se terminant par le pied de page qui confirme que le rapport a été généré automatiquement.


4. Rendu

Enfin, vous assemblez tout. Vous utilisez jinja2 pour renseigner les emplacements dans le HTML avec vos données, puis WeasyPrint convertit cette chaîne HTML en un fichier PDF :

from jinja2 import Environment, FileSystemLoader
from weasyprint import HTML
from datetime import date

env = Environment(loader=FileSystemLoader(".")) template = env.get_template("report.html")

html = template.render( studio_name=STUDIO_NAME, studio_logo=STUDIO_LOGO, project_name=PROJECT_NAME, report_date=date.today().isoformat(), rows=report, )

HTML(string=html, base_url=".").write_pdf(OUTPUT_PDF)

print(f"PDF generated: {OUTPUT_PDF}")

La première partie du code configure Jinja2 pour charger un modèle HTML depuis le répertoire courant, puis récupère le report.html mentionné plus haut.

Ensuite, le modèle est rendu en un document HTML complet en injectant des données d’exécution dans ces emplacements. Les métadonnées du studio et du projet sont transmises, et la date du jour est générée au format ISO. Le résultat de cette étape est une simple chaîne HTML dans laquelle toutes les valeurs dynamiques sont déjà résolues.

Enfin, le HTML rendu est confié à WeasyPrint, qui analyse le HTML, ainsi que tout CSS et ressources associés, puis le convertit en fichier PDF. Le paramètre base_url permet de garantir que les chemins relatifs vers les images ou feuilles de style fonctionnent correctement, et le PDF final est écrit vers le chemin de sortie avant d’afficher un message de confirmation.

Nous obtenons ce résultat final :

Vous pouvez essayer d’exécuter le script vous-même en une minute en clonant notre dépôt Github correspondant.


5. Conseils d’automatisation

L’automatisation est là que ce workflow prend vraiment toute sa valeur : une fois que votre script de rapport fonctionne en local, l’étape suivante consiste à s’assurer qu’il tourne de façon fiable sans intervention humaine, et que la sortie arrive là où les gens regardent déjà.

Au lieu d’exécuter le script manuellement, configurez une tâche cron sur votre serveur pour l’exécuter à un moment prévisible. Par exemple, lancer le script chaque jour de la semaine à 18h00 permet de générer le PDF pendant la nuit et de le préparer avant le début de journée des producteurs. C’est particulièrement utile pour les suivis quotidiens « burn-down » ou les résumés de statut des plans.

Une fois le PDF généré, utilisez gazu pour le joindre directement à une entité pertinente dans Kitsu, comme une Production, un Épisode ou une tâche récurrente. Cela transforme votre rapport en un livrable de premier ordre, avec un historique permanent. Par exemple, envoyer le rapport de chaque journée à une tâche « Daily Production Report » facilite l’audit des changements dans le temps ou la référence à des décisions passées. Astuce pratique : incluez la date à la fois dans le nom du fichier et dans le commentaire de la pièce jointe, afin que les rapports soient faciles à parcourir dans l’interface Kitsu sans devoir les télécharger un par un.

Pour pousser le rapport directement aux parties prenantes, utilisez le smtplib intégré à Python (ou un service d’e-mails transactionnels) pour envoyer le PDF en pièce jointe. C’est idéal pour les producteurs ou clients qui ne vivent pas dans Kitsu toute la journée. Un modèle concret consiste à envoyer un court résumé dans le corps du message — « Plans bloqués : 12, plans finalisés : 3 » — puis à joindre le PDF complet pour les détails.

Au lieu de coder en dur une seule mise en page HTML, stockez plusieurs modèles Jinja2 comme client_report.html et internal_audit.html pour générer différents styles de rapports à partir des mêmes données Kitsu. Par exemple, des résumés propres et haut niveau pour les clients et des tableaux plus détaillés pour le suivi interne. Une approche utile consiste à partager des modèles de base et des macros (en-têtes, tableaux, badges de statut) afin que les changements de branding ou de mise en page se répercutent sur tous les types de rapports. Versionnez ces modèles avec votre code : ainsi, vous pourrez reproduire exactement d’anciens rapports si nécessaire.


Conclusion

L’idée majeure ici ne concerne pas seulement les PDF : il s’agit de récupérer du temps et de l’attention pour le travail qui fait vraiment avancer une production !

En extrayant des données structurées de Kitsu avec Gazu, en les façonnant avec Python, puis en les rendant en rapports automatisés et soignés, vous remplacez une routine manuelle fragile par un système reproductible qui tourne tranquillement en arrière-plan. Ce qui prenait autrefois des heures de copier-coller, de mise en forme et de double vérification devient un pipeline fiable : des données exactes, livrées à temps, dans un format que les producteurs et les clients ont réellement envie de lire. Les rapports personnalisés vous permettent de communiquer l’avancement avec confiance, de mettre en évidence les problèmes avant qu’ils ne deviennent un crunch, et de présenter votre studio comme à la fois créatif et rigoureux techniquement.

Plus votre pipeline est complexe, plus il devient important de créer des rapports personnalisés : assurez-vous donc de lire davantage de nos guides de script pour vous inspirer !

📽️
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 personne. 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.