Anatomie eines Blender-Add-ons das mit OAuth und REST spricht — ohne dass die UI einfriert
Blenders bpy-API läuft im Main-Thread. Ein blockierender HTTP-Call für den 500-MB-.blend-Upload lässt Blender 90 Sekunden lang „nicht mehr reagieren“ — und die meisten User zwingen den Prozess zum Neustart. Der Fix ist ein Background-Worker mit einem Timer-Callback ins Main-Thread, plus OAuth-Device-Flow (kein Browser-Callback nötig).
Unser zer0one-blender-addon (auf GitHub) fügt Blender ein File → Send to ZER0ONE Lab-Menü hinzu. Klick, und die aktuelle Szene wird ans Cinema-Render-Backend geschickt. Erste Version hat ~2 Wochen gebraucht — die ersten Tage ging jede Iteration mit „warum reagiert Blender nicht mehr" zurück. Die drei Probleme die dabei zu lösen waren, sind einigermaßen typisch für alle Blender-Add-ons die mit externen APIs sprechen wollen.
Problem 1: Der Auth-Flow ohne Browser-Callback
Standard-OAuth-Flow: User klickt „Login", Browser öffnet sich, User autorisiert auf der Provider-Site, Provider redirected zurück auf einen localhost:8080/callback-Endpoint, deine App liest den Code aus der URL. Funktioniert für Web-Apps. In Blender: nein — Blender kann keinen HTTP-Server im Hintergrund starten (bzw. es geht, aber es bricht auf Windows-Firewall-Setups, macOS-Sandbox und einigen Linux-Distros mit unterschiedlichen Fehlerarten).
Die saubere Lösung ist OAuth 2.0 Device Flow (RFC 8628). Der Flow:
- Add-on macht
POST /oauth/device/codemit Client-ID. Server antwortet mitdevice_code,user_code,verification_uri. - Add-on zeigt dem User: „Öffne
https://zer0onelab.com/devicein deinem Browser und gib den CodeABCD-1234ein." User macht das (auf einem beliebigen Gerät — Handy, anderer Laptop, egal). - Add-on poll't
POST /oauth/tokenmit demdevice_codealle 5 Sekunden. Server antwortet mitauthorization_pendingbis der User bestätigt hat, dann mit dem echten Access-Token.
Kein Browser-Callback, kein HTTP-Server im Blender-Prozess. Der User macht die Autorisierung auf dem Gerät seiner Wahl. Auf einem Laptop mit lokalen Browser gleicher Rechner, auf Studio-Rendermaschinen die keinen Browser haben genauso.
Implementierungs-Note: Blenders eingebettetes Python hat kein requests, aber urllib.request reicht für alle OAuth-Calls. Das spart eine Dependencies-Bundle-Frage die sonst versionierungs-Hell wird.
Problem 2: Async ohne asyncio (weil bpy nicht mit asyncio spielt)
Blender startet Python im Main-Thread. bpy.ops und alle Scene-Modifikationen müssen im Main-Thread laufen — wenn du versuchst, sie aus einem Background-Thread zu callen, kriegst du entweder einen Crash oder undefined behavior.
Aber ein 500-MB-Upload dauert bei 100 Mbit ca. 45 Sekunden. Wenn du das im Main-Thread machst, ist Blender in dieser Zeit hart eingefroren — Windows zeigt „not responding", macOS färbt das Fenster grau, User schließt den Prozess.
Das Pattern das wir gefunden haben:
class UploadThread(threading.Thread):
def __init__(self, blend_path):
super().__init__()
self.blend_path = blend_path
self.progress = 0.0
self.done = False
self.result = None
def run(self):
# blocking upload, aber im Background-Thread
with open(self.blend_path, 'rb') as f:
# chunked upload mit progress-callback
response = upload_with_progress(f, callback=lambda p: setattr(self, 'progress', p))
self.result = response
self.done = True
# Timer im Main-Thread der den Upload-Status pollt:
def upload_status_poll(thread):
if thread.done:
# Erfolg oder Fehler auswerten, im Main-Thread (bpy safe)
show_result_popup(thread.result)
return None # None = Timer stoppt
# Progress-Bar updaten (bpy.context.scene.frame_current += 0 forces a redraw)
bpy.context.workspace.status_text_set(f"Upload {thread.progress:.0%}")
return 0.2 # nächster Call in 200 ms
Der Trick ist bpy.app.timers.register(upload_status_poll) — Blender ruft den Callback im Main-Thread auf, alle 200 ms. Der Background-Thread macht die eigentliche Arbeit, der Timer kommuniziert den Status zurück. Kein asyncio nötig, keine bpy-Race-Conditions.
Problem 3: Chunked Upload und Retry
Ein 500-MB-.blend-Upload bricht bei einem unterbrochenen WLAN nach 3 Minuten mit „connection reset" ab. Der User muss den Upload komplett neu starten. Nach dem dritten Mal wird das Add-on deinstalliert.
Fix: Chunked-Upload mit Resume-Token. Der Upload wird in 8-MB-Blöcke aufgeteilt. Jeder Block bekommt eine eigene HTTP-PUT-Anfrage. Der Server merkt sich den letzten erfolgreichen Block-Index. Bei einem Reconnect fragt das Add-on nach dem letzten empfangenen Block und startet ab da neu.
Implementiert haben wir das über die S3-kompatible R2-API von Cloudflare (unsere Storage-Backend) mit Multipart Upload. Blender-seitig ist der Code ~120 Zeilen inklusive Retry-Logik. Server-seitig muss überhaupt nichts extra sein — R2 hat das eingebaut.
Was wir noch mitgenommen haben
- Blender 4.2+ hat ein neues Extensions-System. Das alte Add-on-Zip-Format funktioniert weiter, aber neue Add-ons sollten die Extensions-Manifest-Datei mitliefern — dann kann Blender das Add-on über den Blender Extensions Marketplace verteilen. Das ist der SEO-Kanal für Blender-Add-ons.
- Version-Kompatibilität ist ein Committee. Ein Add-on für Blender 4.2 läuft in 4.3 meistens weiter, in 5.0 oft nicht. Wir haben einen
bl_info-Block der explizit „4.2, 4.3, 4.4" listet — Blender warnt sonst. - Users lieben ein Change-Log im Add-on selbst. Wir zeigen bei jeder neuen Version einen kurzen „What's new"-Popup beim ersten Start nach dem Update. Reduziert Support-Anfragen sichtbar.
Meta-Lektion
Ein gutes Blender-Add-on unterscheidet sich von einem schlechten in genau drei Details: Auth ohne Browser (Device Flow), Uploads ohne Freeze (Background-Thread + Timer-Callback), Fehler mit Recovery (Chunked + Resume). Alle drei sind Standard-Distributed-Systems-Patterns aus dem Web-Development, aber in der Blender-Community selten sauber umgesetzt. Wenn du dein Add-on so baust, hebst du dich sichtbar von 80 % der Cloud-Integrations im Blender-Ökosystem ab.
Das komplette Add-on ist Open Source auf GitHub, MIT-lizenziert. Wenn du selbst ein Blender-Add-on baust und Fragen zum Device-Flow oder Chunked-Upload hast — [email protected]. Der Add-on ist einer der Client-Layer von ZER0ONE Lab Cinema Render.
Ähnlicher Brand bei dir?
Wir haben vermutlich schon etwas ähnliches gesehen. Sprich mit uns.
Gespräch starten→