Studio Flow

Production orchestrator wired to ComfyUI, from brief to export

Role
Design and development
Tools
  • Python (stdlib)
  • SQLite (WAL)
  • ComfyUI API
  • n8n
  • ffmpeg
  • Webhook HMAC
  • JavaScript (sans dépendance)
Status
Functional
The dashboard after the real run on 20 Oct 2026: two shots rendered by ComfyUI, durations measured per stage.
The dashboard after the real run on 20 Oct 2026: two shots rendered by ComfyUI, durations measured per stage.
double claims and 0 budget overruns, up to 4 concurrent workers
0
jobs in parallel with 4 workers and 2 GPUs (0.93 with 1 worker)
3.77
model switch instead of 11, thanks to model affinity
1
passing tests (61 before), with no GPU or network
119
The problem
Chaining long renders on a shared machine without losing anything or rendering twice, and delivering only what a human approved.
For whom
An image production that drives ComfyUI and wants human review and proof before any delivery.
The outcome
A queue driving a real ComfyUI (2 shots rendered, hashes verified), resuming a render after a kill -9 without resubmitting it, and scheduling jobs by resources: 3.77 jobs in parallel with 4 workers and 2 GPUs, 0 double claims, 119 tests.

Context

Producing a batch of images means chaining long renders on a shared machine: knowing what actually ran, recovering cleanly after a failure, never rendering the same thing twice, and delivering only what a human approved, with proof.

What I built

  • Real ComfyUI engine: graph submission, tracking, download, using the node pack’s templates (P07) with typed, bounded injection of shot parameters; image, video, animated and audio outputs supported.
  • Resource-aware scheduler: GPU, memory, priorities, anti-starvation and model affinity. 0 double claims and 0 budget overruns up to 4 workers; claim in 0.8 to 6.2 ms, 26 MB worker.
  • Crash recovery: the render ID is written to the database before submission; on restart, the job reattaches to the running render instead of resubmitting.
  • Classified errors: transient ones retried with exponential backoff, permanent ones failed at once; file sha256 checked against the ComfyUI manifest.
  • Dashboard with accounts (PBKDF2), roles, CSRF and tokens; JSON API and HMAC-signed webhook (300 s window, replay refused); versioned export of approved media only.
  • n8n workflow run in a real n8n 2.44: HMAC-signed request received, job created, replay without duplicate (201 then 200).

Architecture 7 blocks

  1. 01 · InputInputsCLI, JSON plan, HMAC-signed webhook
  2. 02 · DataSQLitebriefs, shots, jobs, runs, media, events
  3. 03 · ToolSchedulerGPU, memory, priorities, anti-starvation, model affinity
  4. 04 · ToolWorkerAtomic claim (0.8–6.2 ms), retries, resume, heartbeat
  5. 05 · ModelComfyUIP07 templates, injected and bounded parameters
  6. 06 · HumanReviewApprove or reject each item
  7. 07 · OutputExportApproved only, manifest, CSV, sheet

Pipeline 5 steps

  1. queuedUnique client token, no duplicates.
  2. runningGraph submitted, ID stored.
  3. succeededMedia downloaded, hash verified.
  4. reviewApproved or rejected by a human.
  5. exportManifest, CSV, contact sheet.

Decisions the choice, the reason, the alternative ruled out

  1. D1
    Write the ComfyUI render ID to the database before submitting it.

    After a crash, the job reattaches to the running render: shown by a kill -9 mid-render, a single ComfyUI prompt in total.

    Ruled outRestarting orphaned jobs automatically, at the risk of rendering twice.

  2. D2
    Classify errors: transient ones retried, permanent ones failed at once.

    A passing out-of-memory deserves a retry; a rejected graph does not. Bounded exponential backoff with jitter.

  3. D3
    Check the sha256 of the downloaded bytes against the manifest written by ComfyUI.

    What is exported is proven identical to what was rendered; rechecked at export.

  4. D4
    Stay on the standard library, with a signed webhook that is closed without a secret.

    Runs anywhere; HMAC signature, 300 s window and replay refusal covered by tests.

    Ruled outFastAPI and an open webhook.

  5. D5
    Claim jobs according to declared resources (GPU, memory) with priorities, anti-starvation and model affinity.

    0 double claims and 0 budget overruns up to 4 concurrent workers; 3.77 jobs in parallel with 4 workers and 2 GPUs; 1 model switch instead of 11.

    Ruled outA single worker, one job at a time.

Results

Real runs on 20 Oct 2026 (ComfyUI 0.41, M1 Pro 16 GB)

ScenarioResult
Run: 2 shots submitted to ComfyUI2 succeeded on first attempt, 2 matching hashes
End-to-end time per shot19.2 and 20.2 s; submission 2 ms, download 4–8 ms
Worker killed (kill -9) mid-renderResume: reattached to the same render, a single ComfyUI prompt
Human reviewMedia “to review”, never auto-approved

Resource-aware scheduler

MeasureResult
Double claims, budget overruns (1 to 4 workers)0 / 0
Jobs in parallel, 2 GPUs0.93 with 1 worker, 3.77 with 4
Model switches1 instead of 11 (model affinity)
Claim time0.8 to 6.2 ms
Worker memory26 MB
Automated tests119 (61 before)

Deliverables 5

  • Dependency-free Python package: CLI, worker, simulation and ComfyUI engines, dashboard.
  • Real ComfyUI run and crash-recovery proof, with logs.
  • 119 tests (61 before), including a fake ComfyUI server (errors, OOM, tampered hash, lost prompt).
  • Dashboard with accounts (PBKDF2), roles, CSRF and tokens; ComfyUI video, animated and audio outputs supported.
  • n8n workflow validated by n8n’s own code, signed and idempotent webhook (201, then 200 on replay).

Environment

Hardware and measurement setup

  • Real renders measured on a MacBook Pro M1 Pro 16 GB with ComfyUI 0.41; the scheduler places workers according to the declared GPUs and memory.
  • Python 3.11+ and ffmpeg, no other dependency; dashboard served locally.

Reproduce README commands

Private code: read access under NDA, or a 30-minute live demo. Request access →

./demo.sh
python3 -m studio_flow templates
python3 -m studio_flow plan-import exemples/plan-vecteur-comfyui.json --submit
python3 -m studio_flow worker
python3 -m studio_flow --config demo/studio-flow.toml serve
python3 -m pytest
  • Python 3.11+ and ffmpeg; ComfyUI on 127.0.0.1:8188 for the real engine.
  • The webhook stays closed until STUDIO_FLOW_WEBHOOK_SECRET is set.

Gallery 2

A job’s detail: ComfyUI render ID, timed stages, media and verified hash.
Human review: nothing is exported without approval.

What this project means for you

The same know-how, on your problem.

01

Orchestrating your production

Shot-by-shot tracking, clean recovery and mandatory review: nothing reaches the client without approval.

02

Your ComfyUI, driven

Your workflows become parameterised templates, called by n8n, a script or your internal tool, without duplicates.

03

Proven robustness

Double delivery, crash, engine error, missing output, cancellation: every case is tested before go-live.