Sizzle Video Pipeline
AI storyboards from a spreadsheet, with the real pack composited back in
A spreadsheet-driven AI storyboard pipeline for two CPG campaigns, with a three-stage system that renders the client's actual packaging correctly — the one thing AI alone gets wrong.
AI look development handles everything except the pack; a deterministic compositing pass drops the real wrapper in, then one masked, low-denoise AI pass melts the seam away.
Two delivered cuts
Everything below exists because these shipped.
Note the encodes here are the site's compressed copies; the delivered masters are full-resolution ProRes/H.264. Every beat you'll meet below is visible in these cuts.
One workbook is the single source of truth
Sizzle-Prompts-Master, v2 through v6 — seven tabs, from README to Runtime Summary.
Every beat is a row. Every row fans out into five parallel prompts — one tuned for each model family the beat might render through — plus its VO line and duration. Change the row, and every downstream artifact regenerates from it.
| Beat | Mode | Title | Dur | Prompt columns per row |
|---|---|---|---|---|
| 05 | HERO | Hero Reveal — pack on a honey-lit pedestal | 4.0s | Stage B (QwenEdit, ComfyUI) · Z-Image Turbo + Brand LoRA · Universal cross-model · i2v motion (Kling/Runway/Veo/Seedance/Luma) · VO |
| 02 | GRAPHIC | The Insight — "SUGAR." typographic frame | 2.5s | |
| 12 | LIFESTYLE | Fridge Reach | 3.0s |
Real rows, verbatim from the Oaties Master tab. The Runtime Summary tab adds the durations up so the reel length is known before a single frame renders.
The pipeline is code, and the code is the deliverable too
| Tool | Lines | What it does |
|---|---|---|
| bake_prompts.py | 468 | Reads the workbook, writes the ComfyUI graph — the 103-node storyboard baker below is its output, not a hand-drawn patch bay. |
| storyboard.py | 1,692 | Gated-approval storyboard tool: assembles review PDFs, tracks approve/reject/re-roll per beat, only approved frames move on. |
| sizzle.py | 961 | Cloud image CLI (fal.ai) — batch renders beats when the job runs remote instead of local. |
| motion.py | 1,198 | Image-to-video CLI. Chain mode interleaves holds with start/end-frame bridges so the reel moves without cuts. |
| transitions.py | 461 | Generates within-clip transition motion prompts. |
| composite_pack.py | 679 | Pack-shot preprocessor — compositing the real wrapper into generated scenes. |
| make_captions.py | 202 | Writes per-image caption files for LoRA training. |
| make_manifest.py | 249 | Builds the manifest that drives the storyboard and motion passes. |
| build_storyboard_workflow.py | 349 | The generic graph generator the baker grew from. |
A LoRA learns the identity before anything renders
oaties-lora-z-image.safetensors — 30 image-and-caption pairs, captions written by make_captions.py.
storyboard.py; approve, reject, or re-roll a beat.Queue once, the whole board renders
Both graphs below are the live workflows, exported from the running ComfyUI — shown with the frames each lane actually rendered.
Every lane's frame, straight off the graph
Oaties — 18 beats:
Low Sugar — 15 beats:
These are the raw lane outputs, not retouched picks — the honest state of a board the moment the queue finishes. The versions behind each pick live in the beat boards on the Mondelēz case study.
Rest on a beat — the draft becomes the pick
Every cell starts on an early candidate and melts into the frame that was approved. The distance between the two is the loop doing its job.
Oaties:
Low Sugar:
Same script, newer models
Concept cheap, polish expensive — the local pipeline locked what each beat is, then the approved beats were re-rendered through the newer models (nano banana 2, seedance). Rest on a cell to watch the jump.
Low Sugar — local lane → new-model board, all 15 beats:
Oaties — local frame → the new pass in motion:
This order is the economics of the whole system: iteration happens where frames cost nothing, and the expensive models only ever render beats that already earned their place on the board.
The reel assembles, then gets finished properly
motion.py chain drives the video pass from the manifest — holds on the approved frames, start/end-frame bridges between them, so an 18-beat reel cuts like one continuous move. Everything lands in After Effects (oaties_sizzle_v06.aep — 18 beat comps, brand type and endframe, grade and mix), because the last ten percent is still craft: type never generated, grade never guessed.
Generated Pack vs. Composited Pack
The same beat, twice. Left: the generated draft — a plausible box with a garbled wordmark. Right: the approved frame, with the real pack art segmented with SAM 2, auto-aligned, colour-matched, and knitted in with one low-denoise pass.
Project Elements
Have a Project in Mind?
Animation direction, VFX and creative technology. Message me on LinkedIn or get in touch.