An AI content-creation pipeline. You give it one line — "Create a 30-second cinematic advertisement for a futuristic electric motorcycle" — and it runs a multi-stage workflow that produces a complete, validated production package (brief → concept → scenes → shots → generation-ready prompts) and then renders real media: a storyboard of generated stills, a voiceover, and an assembled MP4.
- Live demo: https://reel-pipeline-production.up.railway.app
- Access: sign in with any Google account (the app is secured with Google OAuth). You may see a one-time "Google hasn't verified this app" screen — choose Advanced → continue; the app only requests basic profile/email.
Note on the free tier. Everything runs on free tiers, and every AI step is an ordered fallback chain so no single provider's quota or outage fails a run:
Stage Chain (first available wins) LLM Gemini → Groq Image Cloudflare FLUX → Gemini → Pollinations (keyless) Voice Deepgram Aura → edge-tts → gTTS (keyless) Video ffmpeg Ken-Burns assembly (no API) Only
GEMINI_API_KEYis strictly required; adding the others improves quality and resilience. When all providers for a stage are exhausted, the pipeline fails cleanly at that stage with a clear message rather than crashing — that fault behaviour is intentional and visible in the UI. See ARCHITECTURE.md for the reliability design.
The finish line is a ProductionPackage (full schema in
backend/app/pipeline/schemas.py):
- Brief — normalized request (product, proposition, audience, tone, duration, aspect) + recorded assumptions
- Concept — logline, narrative arc, visual style, palette, pacing, music direction
- Scenes → Shots — a contiguous timeline with per-shot camera, lighting, on-screen text and voiceover
- Generation-ready prompts —
image_prompt,video_prompt,negative_promptper shot (this is the structured output a downstream text-to-video model consumes) - Rendered media — storyboard stills, voiceover clips, and a final assembled MP4
A real sample is in samples/.
Requirements: Python 3.11+ and ffmpeg on your PATH.
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then edit .env (see below)
uvicorn app.main:app --reload --port 8000Open http://localhost:8000.
GEMINI_API_KEY=... # https://aistudio.google.com/apikey (free)
SESSION_SECRET=any-long-random-string
Leave GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET blank for local dev and the
app uses a dev-user bypass (no OAuth setup needed). Set them to enforce real
Google login (required in any deployment — see below).
Optional but recommended (each is a free fallback that improves resilience/quality):
GROQ_API_KEY (LLM failover), CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN
(better images), DEEPGRAM_API_KEY (better voice). See .env.example for where
to get each.
cd backend && pytest # unit (timeline math) + an end-to-end orchestrator run with fault injection- Google Cloud Console → APIs & Services → Credentials → Create OAuth client ID → Web application.
- Authorized redirect URI:
- local:
http://localhost:8000/auth/callback - prod:
https://<your-app>.up.railway.app/auth/callback
- local:
- Put the client id/secret and the matching
OAUTH_REDIRECT_URIin.env.
With credentials set, every /api/* route requires a signed-in Google user; the
SSE stream authenticates via the same session cookie.
The repo ships a Dockerfile (installs ffmpeg) and railway.json (health check
on /health).
- New Project → Deploy from GitHub repo (root = this
project/folder), orrailway upfrom the CLI. - Add a Volume mounted at
/app/backend/media(generated media) — and optionally one for/app/backend/data(the SQLite DB) so runs survive redeploys. - Set service Variables (from
.env.example):GEMINI_API_KEY,SESSION_SECRET,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,OAUTH_REDIRECT_URI=https://<app>.up.railway.app/auth/callback,PUBLIC_BASE_URL=https://<app>.up.railway.app. - Add the same redirect URI to your Google OAuth client.
- Deploy, then open the public URL.
All routes except /health require authentication.
| Method | Route | Purpose |
|---|---|---|
GET |
/health |
Liveness + whether OAuth is configured |
GET |
/auth/login · /auth/callback · /auth/logout |
Google OAuth flow |
GET |
/api/me |
Current user |
POST |
/api/jobs |
Start a pipeline run — {"request": "..."} → {"id","status"} |
GET |
/api/jobs |
List your runs |
GET |
/api/jobs/{id} |
Job status, error, and the full package |
GET |
/api/jobs/{id}/events |
SSE stream of live stage progress (replays history, then tails) |
curl -X POST https://<app>.up.railway.app/api/jobs \
-H 'Content-Type: application/json' \
--cookie "session=<from-browser>" \
-d '{"request":"Create a 30-second cinematic advertisement for a futuristic electric motorcycle."}'
# -> {"id":"6742b0756d89","status":"queued"}Full response body: samples/sample_response.json.
- ARCHITECTURE.md — design decisions, the pipeline, reliability/fault-tolerance, scalability, trade-offs, and assumptions.