# Video pipeline findings (read-only dossier, 9 Oct 2026)

Repos mapped to the [video workflow page](./index.html). Assessment used GitHub API only: no deploys or credentialed model calls.

## Per repo

### wearecrank-ltd/c-pub-brief, Stage 1 Concept

| | |
|---|---|
| **Role** | Vertical/product prompt → Perplexity research → markdown brief committed to `runs/` |
| **Inputs** | User prompt |
| **Outputs** | Markdown with YAML frontmatter (no structured concept JSON) |
| **Hand-off** | Markdown in repo → **manual** Crank-brand deck → G1 |
| **Tests / CI** | No tests; no `.github/workflows` (Dependabot only) |
| **Last commit** | 29 Jun 2026, homepage copy |
| **Deploy** | Cloudflare Workers (`the-pub-brief`); manual wrangler |

**State:** No CI · unauthenticated `/api/research` (Perplexity spend) · README still points at old `peterjabraham/the-pub-brief` · nine open Dependabot PRs.

---

### peterjabraham/video-ad-analyzer, Stages 2-3 Brief & Script

| | |
|---|---|
| **Role** | Reference ad analysis, Claude script generation, Google ABCD gap scoring (ignore other tabs for this pipeline) |
| **Inputs** | Brief / references; script in browser state |
| **Outputs** | Rich script JSON (`beats`, `directorTable`, `production`); MD/TXT export only |
| **Hand-off** | **Manual** Crank-brand deck → client/script approval → paste/upload into storyboard-gen |
| **Tests / CI** | ~217 vitest tests locally; **no CI workflow** |
| **Last commit** | 20 Jul 2026, Claude API param fix |
| **Deploy** | Railway |

**State:** No CI · **broken hand-off:** `analyzeScriptWithABCD` reads legacy `hook`/`body`/`cta`; new scripts score empty · open `/api/analyze` Claude proxy · JWT falls back to `dev-secret-change-in-production` if unset.

---

### peterjabraham/storyboard-gen, Stages 4-6 Storyboard, look/cast, voice/music (partial)

| | |
|---|---|
| **Role** | Script/PDF → strict `board-spec.json`, supporting MD, one composite board PNG (upscaled) |
| **Inputs** | Script text/PDF; optional reference image (stored, **not sent to image model**) |
| **Outputs** | R2: `{slug}-board.png`, `{slug}-board-spec.json`, `{slug}-supporting-text.md` |
| **Hand-off** | Manual download; session cookie + `X-Requested-With`; no API tokens |
| **Tests / CI** | ~24 vitest (+ Workers pool); **no CI** |
| **Last commit** | 8 Oct 2026, Crank UI restyle (most active repo) |
| **Deploy** | Cloudflare Workers `visual-board-generator` |

**Stages 4-6 capability (in this repo today):**

| Capability | Status |
|---|---|
| Look / cast lab | **Partial:** schema + text; no cast images, reference ignored |
| Voice / TTS + word timings | **Missing** |
| Music | **Missing** (`fx_or_sound` text only) |
| Shot manifest / beat map | **Partial:** `shots[]` in JSON; free-string `time_range`, no script beat IDs |
| Keyframe start/end PNGs | **Missing:** one composite board only |
| Hand-off to ugc-studio | **Broken:** markdown is JSON code blocks; ugc parser expects `### Scene N` → **0 scenes** |

---

### peterjabraham/batch-image-vid-test, Keyframes (side input to stage 4)

| | |
|---|---|
| **Role** | Batch ad stills (formats + `manifest.json`); Brand Hub; **no video, no start/end pairing** |
| **Inputs** | Brief, CSV campaign, references (bytes not sent to model) |
| **Outputs** | `output/<batchId>/` + `manifest.json` |
| **Hand-off** | Library URLs/files; not wired to storyboard-gen or ugc-studio |
| **Tests / CI** | Crop tests only; **no CI** |
| **Last commit** | 31 Aug 2026, Campaign tab |
| **Deploy** | Railway (Docker) |

**State:** No CI · no server auth (CORS only) · misleading repo name.

---

### peterjabraham/ugc-studio, Stage 7 Rough cut

| | |
|---|---|
| **Role** | Higgsfield proxy: Soul stills + image-to-video (first frame only); script/scene model |
| **Inputs** | Script markdown (expected format) or manual entry; first-frame image URL |
| **Outputs** | Separate clip URLs on Higgsfield (~7 day retention); **no concat, VO, music, or master MP4** |
| **Hand-off** | Manual NLE assembly; **no final assembly step in repo** |
| **Tests / CI** | 27 mocked integration tests; **no CI** |
| **Last commit** | 23 Jul 2026 (2 commits total); likely **outdated** vs Higgsfield catalogue (Kling 3.0, Seedance 2.x) |
| **Deploy** | CF Workers prod + staging |

### ugc-studio: keep / refactor / replace?

**Recommendation:** **Refactor in place** short term (board-spec importer, model ID upgrades, R2 copy), plan **replace assembly** with a containerised ffmpeg stage. Full replace of the Worker is lower priority than fixing imports and adding a real rough-cut assembler.

### Cost of one finished 30 s rough cut (video generation)

**Assumptions (all per-30s USD figures below are estimates):** ~6-8 shots; **1.5×** handles on keeper footage; **3×** reroll multiplier → **135 generated seconds** per finished 30 s (`30 × 1.5 × 3`). Arithmetic is **estimate** = cited vendor rate × 135 s. **Video generation only** unless the row says otherwise. At 2× rerolls use 90 gen-s (×0.67); at 4× use 180 gen-s (×1.33).

| Route | Rate used (USD) | Est. per finished 30 s | Source |
|---|---|---|---|
| **Wan 2.2 14B, H100 PCIe** (rented) | RunPod H100 $1.99-2.89/h; ~5 min/5 s clip | **Estimate ≈ $4.50-9.40** (incl. ~1 h setup/idle) | Timing: [powergpu.ai Wan guide](https://powergpu.ai/guides/wan-video-generation-gpu) · Price: [RunPod pricing](https://www.runpod.io/pricing) |
| **Wan 2.2 RunPod Public Endpoint** | $0.30 / 5 s 720p clip | **Estimate ≈ $8.10** (27 clips × $0.30) | [RunPod pricing](https://www.runpod.io/pricing) (Public Endpoints) |
| **Veo 3.1 Fast, Gemini API** (720p / 1080p, with audio) | $0.10/s / $0.12/s | **Estimate ≈ $13.50 / $16.20** | [Gemini API pricing](https://ai.google.dev/gemini-api/docs/pricing) |
| **Veo 3.1 Fast, Vertex** (video+audio, 720p / 1080p) | $0.10/s / $0.12/s | **Estimate ≈ $13.50 / $16.20** | [Vertex AI generative pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) |
| **Kling 3.0, Kling API** (1080p silent) | $0.112/s | **Estimate ≈ $15.12** | [Kling API video pricing](https://kling.ai/document-api/pricing/base/video.md) |
| **Kling 3.0, via Higgsfield** (ugc-studio path) | from $0.112/s | **Estimate ≈ $15.12+** | [Higgsfield API rates](https://higgsfield.ai/blog/higgsfield-api) |
| **Runway gen4.5** | 12 credits/s ($0.01/credit) | **Estimate ≈ $16.20** | [Runway API pricing](https://docs.dev.runwayml.com/guides/pricing/) |
| **Veo 3.1 Standard, Gemini API** (1080p, with audio) | $0.40/s | **Estimate ≈ $54** | [Gemini API pricing](https://ai.google.dev/gemini-api/docs/pricing) |
| **Sora 2 / Sora 2 Pro** | was $0.10-0.70/s | **Unavailable** (API retired 24 Sep 2026) | [Sora 2 Pro model page](https://developers.openai.com/api/docs/models/sora-2-pro) |

**All-in estimates (video + keyframes; arithmetic estimate, not a single vendor SKU):**

| Bundle | Est. per finished 30 s | Basis |
|---|---|---|
| Veo 3.1 Fast + Nano Banana 2 keyframes | **Estimate ≈ $17-20** | Video row above + keyframes table below |
| Kling 3.0 + gpt-image-2 high keyframes | **Estimate ≈ $30-38** | Video row above + keyframes table below |
| Open model on rented H100 (Wan) | **Estimate ≈ $10-15** | Wan H100 row + keyframes; plus staff/ops time (not priced) |

### Non-video line items per finished 30 s (estimates)

| Item | Basis | Est. cost | Source |
|---|---|---|---|
| Keyframes (48 images: 8 shots × 2 frames × 3 rerolls) | gpt-image-2 high ~$0.32/image; Nano Banana 2 $0.067/image | **Estimate ≈ $15** / **≈ $3.20** | Rate logic in `peterjabraham/batch-image-vid-test` `estimateCost.ts` (external repo); list prices: [Gemini API pricing](https://ai.google.dev/gemini-api/docs/pricing) · [Vertex generative pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) |
| VO / TTS (30 s × 5 takes) | Gemini Flash TTS $0.00225 / 10 s audio | **Estimate < $0.05** | [Gemini API pricing](https://ai.google.dev/gemini-api/docs/pricing) · [Vertex generative pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) |
| Word timings (alignment / transcription) | Gemini Transcribe ~$0.0051 / audio minute | **Estimate < $0.01** | [Vertex generative pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) |
| Music bed (30 s × 5 options) | Lyria 3 clip $0.04 each | **Estimate ≈ $0.20** | [Vertex generative pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) |
| Assembly (ffmpeg in container) | CPU marginal | **Estimate ≈ $0** | No vendor meter; container hosting priced separately |

---

## Proposed shared hand-off: `handoff.v1`

Goal: every stage output gets a stable `output_id` and shareable URL; the next stage **picks** the latest **approved** parent or **uploads** an amended file, recording `source` and `parent_ids`. See design mocks on the [workflow page](./index.html).

**Where it lives:** files in **R2** (immutable blobs keyed by `output_id` + role); metadata in a **registry** (D1 table or KV) behind one **Cloudflare Worker** with token auth. Endpoints: `POST /handoff` (register), `GET /handoff/{output_id}`, `GET /handoff/latest?stage=stage-03-script&approval_state=approved` (feeds pick dropdowns), `PATCH /handoff/{output_id}/approval` (gate transitions).

**Schema fields:** `schema`, `output_id` (stage-prefixed ULID, e.g. `s03-01J9HQ4SCRIPT`), `stage`, `version`, `approval_state` (`draft` | `in_review` | `approved` | `client_amends`), `approved_by`, `approved_at`, `gate`, `source` (`picked` | `uploaded`), `parent_ids[]`, `files[]` (`role`, `mime`, `url`, `sha256`, `size`). Payload bodies can still use typed JSON (`concept.v1`, `script.v1`, `board-spec.v1`) as `files[].role` entries inside the envelope.

```json
{
  "schema": "handoff.v1",
  "output_id": "s03-01J9HQ4SCRIPT",
  "stage": "stage-03-script",
  "version": 2,
  "approval_state": "approved",
  "approved_by": "peter@wearecrank.com",
  "approved_at": "2026-10-09T11:00:00Z",
  "gate": "G3",
  "source": "uploaded",
  "parent_ids": ["s02-01J9HQ4INTAKE"],
  "files": [
    {"role": "script.v1", "mime": "application/json", "url": "https://registry.example/r2/s03-01J9HQ4SCRIPT/script.v1.json", "sha256": "abc…", "size": 18432},
    {"role": "abcd-report", "mime": "application/json", "url": "https://registry.example/r2/s03-01J9HQ4SCRIPT/abcd.json", "sha256": "def…", "size": 4096}
  ]
}
```

**Per repo (emit → accept):**

| Repo | Emit as `handoff.v1` | Accept at input |
|---|---|---|
| **c-pub-brief** | After research/save: markdown + future `concept.v1` JSON; stop writing only to GitHub `runs/` without registry | Prior concept pick N/A; optional brand kit refs by URL |
| **video-ad-analyzer** | Script JSON + ABCD report + exports as files; gate G2/G3 approval on registry | `parent_ids` from concept/brief handoff; pick or upload deck amends |
| **storyboard-gen** | `board-spec.json`, board PNG, supporting MD from R2 today → register under one `output_id` | `parent_ids` from approved script handoff (replace paste/upload) |
| **batch-image-vid-test** | `manifest.json` + still URLs per batch (`sKF-…` ids) | Optional `parent_ids` from board brief; consumed by storyboard stage 4 side input |
| **ugc-studio** | Clip manifest JSON + first-frame refs (future assembled rough cut) | `parent_ids` from `board-spec` handoff (adapter, not markdown); pick/upload amends |

This **subsumes** the earlier “versioned pipeline contract” idea: typed payloads stay as `files[]` roles inside one envelope instead of five ad-hoc transports.

---

## Security (brief)

- **Open cost proxies:** c-pub-brief `/api/research`, video-ad-analyzer `/api/analyze`, batch-image-vid-test server (no auth).
- **Default JWT secret** in video-ad-analyzer if `JWT_SECRET` unset.
- Complete `.env.example` files and add auth or rate limits before wider exposure.

---

## Top 5 improvements (impact ÷ effort)

1. **`handoff.v1` registry + Worker (R2 + D1/KV):** one pick/upload path for every stage; replaces re-upload and manual file shuffling. **Subsumes the old versioned pipeline contract item** (typed JSON lives in `files[]` roles).
2. **Automate the two Crank-brand deck steps:** emit `concept.v1` / script handoffs and render decks from Brand Hub; decks become registerable outputs instead of side-channel PDFs.
3. **Fix ABCD + script schema** in video-ad-analyzer: serialise new fields; regression test; write ABCD into `handoff.v1` files.
4. **board-spec.json → ugc-studio adapter + clip R2 archive:** closes zero-scene import; upgrade model IDs (Kling 3.0 / Veo 3.1 Fast).
5. **Assembly stage (ffmpeg container):** manifest timings, VO, music, captions → one rough-cut MP4 registered as stage 7/8 handoff.

---

## Sources (vendor pricing and benchmarks, read 9 Oct 2026)

- [Gemini API pricing](https://ai.google.dev/gemini-api/docs/pricing) (last updated 7 Oct 2026)
- [Vertex AI generative AI pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing)
- [Kling API video pricing](https://kling.ai/document-api/pricing/base/video.md)
- [Runway API pricing](https://docs.dev.runwayml.com/guides/pricing/)
- [Luma API pricing](https://lumalabs.ai/api/pricing)
- [BytePlus ModelArk (Seedance)](https://www.byteplus.com/th/product/modelark)
- [Sora 2 Pro model page](https://developers.openai.com/api/docs/models/sora-2-pro). **OpenAI retired the Sora API on 24 Sep 2026**; do not plan on it.
- [Higgsfield API overview and rates](https://higgsfield.ai/blog/higgsfield-api) (16 Sep 2026) · [Higgsfield Seedance 2 I2V docs](https://docs.higgsfield.ai/docs/models/seedance-2/image-to-video)
- [RunPod pricing](https://www.runpod.io/pricing) (updated 27 Sep 2026)
- [Wan GPU generation timings](https://powergpu.ai/guides/wan-video-generation-gpu) (3 Sep 2026)
- [LTX-2.3 MLX benchmarks](https://huggingface.co/gajesh/LTX-2.3-mlx-fp16) · [LTX-2](https://ltx.io/model/ltx-2)

*Every per-30 s figure is an **estimate** (rate × 135 generated seconds at a 3× reroll multiplier, with 1.5× handles), unless marked unavailable. Re-check vendor rates before budgeting.*
