$0 AI Reels on a 12GB GPU
Wan 2.2 + Lightning LoRA dropped my per-scene render from 50 minutes to 5:37 — here's the swap.
Hi, I’m Daniel — a software engineer, solo builder, and the person behind Digital Craft Workshop.
I’ve spent ten years writing TypeScript, .NET, and React for a living. The last few of them I’ve been building on the side of the day job: B2B SaaS, AI tools like Reel Pipeline Kit and Drippery, internal infrastructure, and a Unity 2D narrative game. Some shipped. Some I killed. Both are useful.
Digital Craft Workshop is for developers, AI builders, and indie founders who’d rather understand the craft than ride the hype. The kind of reader who distrusts gurus and wants AI that’s cheap, practical, and accountable to one engineer in a workshop.
Each essay is something you can read in one sitting and use the same week: an architecture pattern, an AI workflow a single developer can actually run, a build log, or a postmortem on a project that didn’t make it.
Everything here, I actually ran — including the parts that broke.
One evening I had a reel pipeline that worked and a nagging feeling it was lying.
The Ken Burns zoom over a static cover image looked fine on its own.
Side by side with anything actually animated, it looked like a slide deck pretending to be a video. I wanted real motion: a graph that fills in, a character that moves, without paying $0.50 to $1.50 every time I render a draft I’ll throw away. This is another $0 build from the workshop.
A day later, the same pipeline renders 6 animated scenes on a 12GB RTX 3060 in my home office, reached over Tailscale. The new bottom layer is Wan 2.2 14B I2V (image-to-video) with a Lightning LoRA.
Per scene cost: $0. Per scene time: 5 minutes 37 seconds.
Total reel: 55 seconds, 17.4 MB, 1080×1920. The brand chrome, captions, and DCW header are untouched. Only the bottom layer is different.
TLDR
Ken Burns over a static cover is the cheapest reel motion you can ship, and the one viewers clock as fake fastest.
Wan 2.2 14B I2V + Lightning LoRA: 50 min/scene at 20 steps, down to 5:37 at 4 steps. Same perceived quality.
12GB RTX 3060 over Tailscale = $0 marginal cost per reel. Trade: one ugly 33GB download.
No GPU? Replicate runs the same Wan 2.2 i2v at ~$0.30/scene. The pipeline still ships; only the render location changes.
compose.ts diff: one optional
bgVideofield. Everything else stays identical.
The reel pipeline already had a stable shape.
An LLM splits the article into 3–5 scenes. ElevenLabs narrates each one in my cloned voice. ffmpeg stitches it together with ASS karaoke captions, DCW brand chrome, and 0.4s pauses between scenes.
The thing wrong with it sat in exactly one layer: the background was always a still image with a Ken Burns zoom on top.
The pipeline only swaps one step. | Generated with Claude
So the question wasn’t “rewrite the pipeline.”
It was “what’s the smallest change so the bottom layer is video instead of a panning image, and everything else stays identical?”
The trap I almost fell into
My first instinct was the textbook answer: send each scene’s still image and prompt to a hosted i2v endpoint, get an mp4 back, drop it in. Replicate, Modal, and RunPod all deliver.
Per-scene cost lands around $0.10 to $0.30 depending on resolution and model. A 6-scene reel sits at $0.50 to $1.50.
That number is fine for a production reel. It kills iteration.
I re-render reels constantly: wrong scene cut, audio out of sync, caption typo, brand color drift. If every “let me just try one more” costs a dollar, I stop trying. I’ve watched this exact dynamic kill three of my own side projects already.
So I went looking at local. The first attempt was LTX-Video 2B, fast and comfortable on 12GB.
But ask for “a character climbing a ladder” and you get a vaguely person-shaped smear floating. Killed.
Then Wan 2.2 14B. Semantic understanding is good: you can describe what should happen and it mostly happens.
The problem was speed. At 20 steps per scene, Wan took 50 minutes on my 3060. A 6-scene reel meant 5 hours, a weekend project, not a daily rhythm.
The Lightning LoRA changed the math. It’s a distilled adapter that hits comparable quality at 4 steps instead of 20.
Two 1.17 GB files, same Wan 2.2 base. Render time per scene dropped to 5:37, an 8.5× speedup, and to my eye the quality difference is invisible at reel resolution.
33 GB of models total: high_noise 13.31 GB, low_noise 13.31 GB, umt5_xxl fp8 6.27 GB, wan_2.1_vae 236 MB, plus the two LoRAs. The PC rebooted in the middle of the download, which is its own small story.
// Resume the download instead of starting over.
curl -C - -o wan2.2_high_noise_14B.safetensors \
https://huggingface.co/.../wan2.2_high_noise_14B_fp8_scaled.safetensors
// Scheduled task that retries on reboot.
schtasks /create /tn “WanResume” /tr “C:\resume.bat” /sc onstart
What actually changed in compose.ts
The composition layer barely changed. compose.ts already had a ScenePart type that described what each scene needed: the audio, captions, and chrome. I added one optional field.
type ScenePart = {
audio: Buffer;
captions: AssSubtitle;
bgImage: Buffer; // existing
bgVideo?: Buffer; // new
durationFrames: number;
};
When bgVideo is present, the ffmpeg branch swaps.
Out: -loop 1 -i bg.png plus the Ken Burns zoom filter. In: -i bgvideo.mp4 with scale, crop, fps=30, and tpad to handle the 0.4s pause.
Everything above that bottom layer runs identically. The header, accent bar, content card, and karaoke captions all stay put, each word still lighting up in the accent color as it’s spoken. The composition shape stays stable; the bottom swaps.
This is the pattern I keep reaching for: stable composition, swappable bottom layer.
The same shape shows up elsewhere. Article covers swap the prompt and keep the brand template. Email sends swap the body and keep the wrapper.
When the shape fits in my head, the swap is small enough that I’ll actually do it on a weeknight.
Three fixes that weren’t obvious
Scene 3 ran 281 frames at 16fps, about 17.5 seconds, the longest narration beat. Wan OOM’d at 12GB. The honest fix was to split the render, not buy a bigger GPU.
I render the first 141 frames. Extract the last frame as a PNG. Feed that PNG as the start_image for the second 141 frames.
Then concatenate the two clips with ffmpeg using -ss 0.0625 on the second clip to drop the duplicate frame at the seam. The seam is invisible. The trick is that Wan’s start_image conditioning is strong enough to keep the motion continuous across the cut.
The second fix was prompt-related and embarrassing. Scene 2 had a shot of a blank red board on a workshop wall.
Wan kept hallucinating the word “WORKSHOP” onto it, in different fonts each generation, like the model couldn’t accept that a red board would just be red. The fix:
// Positive prompt
“A plain red board on a wooden workshop wall, no text, no letters.”
// Negative prompt (load-bearing).
“text, letters, writing, words, signage, logos, labels”
The negative prompt was the actual fix. The positive “no text” alone wasn’t enough; Wan reads “text” as a concept worth representing. The negative tells it the concept isn’t allowed in the output.
I had to learn this by watching three generations produce “WORKSHOP” and “WORK SHOP” and “WRK SHP” before I stopped and read the prompt like a stranger would.
Third fix was per-scene length. The first version passed a fixed 97-frame length to every scene because that’s what the Wan example used.
The result: every scene was the same duration regardless of how long the narration actually was. Short beats had Wan animation hanging on after the voice stopped. Long beats had Wan cutting off mid-motion.
The fix read the timing from the narration itself. I take the last word’s end timestamp from the audio JSON, add the 0.4s scene pause, then multiply by 16fps.
Per scene: 49, 169, 281, 185, 165, 41 frames. The animation now ends when the sentence ends, instead of hanging on after the voice or cutting off mid-motion.
Why home PC, not cloud
I have a 12GB RTX 3060 in a desktop in the corner of my office. It runs ComfyUI as a service and exposes port 8188 on the local network, and I reach it from my laptop over Tailscale. The whole reel pipeline runs from my laptop and hits the home PC for the Wan render step.
This is the same reflex that pushed me to self-host my memory instead of paying $2/mo. I usually move side projects off my computer, but GPU rentals flipped the math.
For Article Forge specifically, I keep choosing this over Replicate. For one-off productions Replicate is genuinely the right call.
But for a tool I’m using daily, where I’ll re-render the same reel six times in an evening tweaking captions and pacing, the cloud bill compounds. The home PC sits idle 95% of the time anyway. Marginal cost of the next render is $0, just electricity.
The trap is treating “I already own the hardware” as free. It hides real costs: a 33GB download, ongoing ComfyUI upkeep, a Tailscale dependency, and a home PC that strands me if it reboots mid-render.
Without the hardware already in the room, $0.50 a reel on Replicate wins easily. I happen to have the box humming in the corner, so the next render just costs electricity.
If you don’t have the GPU
The pipeline doesn’t care where the bytes come from. The bgVideo field on ScenePart just needs an MP4 buffer per scene. Whether that buffer came off my home PC or a cloud render is invisible to ffmpeg.
The cloud swap is one function call:
// Replicate Wan 2.2 i2v
const output = await replicate.run(
“wavespeedai/wan-2.2-i2v-a14b”,
{ input: { image, prompt, num_frames: 81, fps: 16 } }
);
const bgVideo = Buffer.from(await (await fetch(output)).arrayBuffer());
Per-scene cost: ~$0.30. A 6-scene reel: ~$1.80, about what one ElevenLabs Starter quota refresh costs you.
If you re-render a reel six times in an evening, that’s $11. Painful for iteration, fine for one-shot production. The escape hatch: render each scene once with a cheap variant, lock the good ones, only re-run the failures.
Modal and RunPod work the same way: different SDK, same Wan 2.2 i2v endpoint. The kit ships an 8GB-VRAM ComfyUI workflow for an older card, and a no-GPU Ken Burns workflow for people who don’t want a GPU at all.
It’s a one-machine setup. It fits in my head. That’s load-bearing for me.
If you want this exact pipeline (the 12GB workflow, the 8GB fallback, and the no-GPU Ken Burns variant), it ships as the Reel Pipeline Kit this summer. Join the waitlist and you’ll get it the day it’s out.
And if you’ve ever zoomed over a still and called it motion, restack this for the next person rendering reels at $0.
P.S. Digital Craft Workshop ships one build like this a week, same setup, different small failure. Subscribe and we’ll compare notes.








