Back to articles
AI Engineering
Aug 5, 2026
15 min read

I Built an Autonomous AI Video Pipeline for Under $1 per Video (Terminal-First, No n8n)

Most "AI content automation" stacks are a subscription graveyard: Apify for scraping, ElevenLabs for voice, Shotstack for rendering, n8n for glue, and a Claude bill on top. I built the same pipeline for <$1 per video — orchestrated from the terminal, with OpenCode as the LLM brain. The full source is on GitHub: pipeline-contenido-ia.

The Architecture

Seven stages, one feedback loop. Signals feed an immutable wiki; a bandit picks what to make; cheap models produce it; FFmpeg assembles it; YouTube publishes it; analytics close the loop by feeding real revenue data back into the decision layer.

1. SIGNALS     yt-dlp + pytrends + Reddit JSON        ($0)
2. WIKI BRAIN  markdown + CLAUDE.md schema, git-versioned
3. DECISION    OpenCode CLI + epsilon-greedy bandit    ($0*)
4. PRODUCTION  edge-tts + fal.ai video + Pillow thumbs (~$0.60)
5. ASSEMBLY    local FFmpeg: captions, ducking, loudnorm ($0)
6. PUBLISH     YouTube Data API, synthetic-content flag  ($0)
7. FEEDBACK    YT Analytics → SQLite → bandit reward     ($0)

*The LLM tier runs on OpenCode Go's free models: kimi-k2.6 for orchestration and scripts (balanced), deepseek-v4-flash for bulk tasks like comment mining and SEO metadata.

The Upgrade Table (Where the Money Was Saved)

| Original idea | Cost | Shipped instead | Cost | |---|---|---|---| | Apify / Firecrawl / VidIQ | $60–350/mo | yt-dlp + pytrends, velocity ratio computed in-house | $0 | | Claude API orchestrator | $30–100/mo | OpenCode CLI, opencode-go free tier | $0 | | ElevenLabs + Dubbing | $5–330/mo | edge-tts neural voices + cheap-LLM translation | $0 | | Suno / Epidemic Sound | $10–24/mo | YouTube Audio Library / CC-BY (zero Content ID risk) | $0 | | Shotstack / Remotion | $20/mo | local FFmpeg (static binary inside the venv) | $0 | | ThumbnailTest | $20/mo | Pillow A/B variants + YouTube's native Test & Compare | $0 | | n8n / Temporal | $5–50/mo | run.sh + cron + SQLite job queue | $0 | | Veo/Kling for every clip | $$$ | LTX-Video default (~$0.02/s) + hard budget guard | ~$0.60/video |

Three Design Decisions That Mattered

1. SQLite is the orchestrator

No n8n, no Temporal, no Redis. One SQLite file holds the job queue, the cost ledger, the metrics, and the bandit state. The runner is a bash script with retries and exponential backoff; cron does the scheduling. When a stage fails, an ntfy.sh push notification hits my phone — free.

2. The bandit decides, the wiki remembers

An epsilon-greedy bandit (ε=0.20) chooses the next video's niche:format arm — 80% exploit what worked, 20% explore. Rewards are net dollars (YouTube revenue minus tracked generation cost), pulled from the Analytics API nightly. Patterns live in a git-versioned markdown wiki with TTLs: a pattern that stops validating expires automatically.

3. Everything has a $0 dry-run mode

Without FAL_KEY, the video stage renders placeholder slates via FFmpeg. The entire pipeline — decision to published private video — is testable at zero cost. Real clips only flow when the estimated cost is under the MAX_VIDEO_COST_USD guard.

The Gotchas (So You Don't Hit Them)

Every one of these cost me real time:

  • YouTube bot-checks yt-dlp full-page extraction from flagged IPs. Flat search keeps working; for full metadata, pass --cookies-from-browser safari.
  • OAuth 403 access_denied = your app is in Testing mode and your Gmail isn't in the Test users list. One-minute fix, hours of confusion if you don't know it.
  • Testing-mode refresh tokens expire in 7 days. Publish the consent screen to Production (unverified is fine for personal use) or your cron silently breaks weekly.
  • Custom thumbnails 403 until the channel is phone-verified at youtube.com/verify. New channel? No thumbnails. Plan for it.
  • An inline comment in .gitignore disabled the rule on that line — nearly pushed mp4s to a public repo. Comments go on their own line. Always.
  • Publish must be idempotent. My thumbnail failure threw after the upload succeeded; the retry loop happily re-uploaded twice more. Record the video ID immediately after insert, skip if present.

Run It Yourself

git clone https://github.com/julio-arcila/pipeline-contenido-ia
cd pipeline-contenido-ia
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt

./run.sh auth                  # YouTube OAuth wizard (one-time)
./run.sh fal-auth --test-clip  # optional: real AI clips (~$0.08 test)
./run.sh signals "your niche"  # scrape + trends + reddit
./run.sh decide                # bandit + LLM -> decision JSON
./run.sh produce  data/decision-*.json
./run.sh assemble data/decision-*.json
./run.sh publish  <video_id>   # private by default
./run.sh analytics             # close the loop

The repo ships with the full architecture doc (PIPELINE.md), an upgraded Mermaid diagram, and a sample decision file so you can see exactly what the LLM brain produces. FFmpeg is bundled inside the venv via imageio-ffmpeg — no system installs needed.

Honest constraint: local video generation needs a GPU this machine doesn't have, which is why fal.ai is the single paid stage. On an M-series Mac with 32GB+, swap the backend to ComfyUI and the cost per video drops to zero.

Sponsored

Build your next project on Cloudflare

Deploy full-stack apps globally with Workers, D1, and R2. Start for free.

Try Cloudflare Workers
0 views

Buy me a coffee

If this article helped you, consider supporting my work. Every coffee fuels the next deep-dive!

Stay in the loop

Get notified when I publish new articles on TypeScript, React, Node.js, and fullstack architecture. No spam, ever.