Storyboard Pro

2025 – present

A self-hosted creative-media studio: describe a film idea, and a local LLM breaks it into scenes, characters, locations and props. You then block each shot in 3D and render it through a headless GPU pipeline as stills, clips, and meshes.

The problem

Turning a story idea into a visual storyboard is slow, repetitive work. You break the idea into scenes, keep characters and locations consistent across dozens of frames, and hand-write an image-generation prompt for every panel.

Text-to-image also gives you almost no control over staging. You can describe “low angle, character on the left” and get something else entirely, every time.

I wanted a tool where you describe the idea once and get an editable storyboard, and where the camera is an actual camera instead of an adjective in a prompt.

What it does

The storyboard: every scene the LLM broke out of the idea, with its cast, locations, props and stills

A local LLM (Qwen3-14B on llama.cpp, speaking OpenAI-compatible HTTP) expands a one-line idea into structured scenes, characters, locations and props, stored in PostgreSQL. Every entity gets a generated, editable prompt profile, and every project gets a style profile. Those profiles are what keep a character looking like the same character from shot to shot, because the model re-reads a stored description instead of inventing a new one each time.

Each scene also carries a master shot list covering size, angle, movement, equipment and audio notes, drafted by the LLM and editable inline. A headless ComfyUI instance renders through 12 or more workflows: Z-Image Turbo, Flux-2 Klein edit, Krea2, plate and outpaint passes, TripoSG and Trellis2 meshes, and image-to-video.

Blocking the shot in 3D

The 3D scene stage: characters and props placed on a stage, framed through a real camera with lens and aspect controls

This is the part I would rebuild the project for. Instead of describing a camera angle, you place characters and props on a stage in the browser with React Three Fiber, then frame the shot through a real camera with a real lens and aspect ratio. The stage renders a color pass that conditions image generation, so the generated frame matches the blocking. Composition, pose and eyeline hold because they were specified geometrically rather than described in words.

The 3D proxies are deliberately rough. A Flux Klein beauty pass then restores the character’s real face from their reference photo while preserving the staged composition, which turns a distorted mesh into a photoreal frame in about two minutes.

Clip Studio: choosing a video workflow, subject and background-plate references, and queueing a clip

Finished stills feed image-to-video (LTX-2.3) and pose-transfer animation. The shot list’s metadata composes the motion prompt, so a wide static crowd shot and a handheld close-up produce materially different clips from the same still.

Architecture

Storyboard Pro architecture: React frontend to FastAPI, which orchestrates PostgreSQL, an LLM API, and a headless ComfyUI GPU worker

Layer Tech GPU
Frontend React + Vite + Tailwind v4 + R3F None
API FastAPI (async) + background job worker None
Engine ComfyUI (headless) device 1
LLM llama.cpp (Qwen3-14B GGUF) device 0
Database PostgreSQL 15 (async SQLAlchemy) None
Side-cars Mesh optimizer, background remover None

The constraint that shaped everything: ComfyUI is an engine, not an API you design. It accepts an entire workflow graph as JSON, and node IDs change whenever the graph is re-exported. I handled that with node maps, a small JSON file per workflow naming the injection points for prompt, seed, input image, reference image and filename prefix. Application code injects values through the map, so adding a model takes two files and no Python.

Other pieces I am happy with:

What broke along the way

What I’d do differently