# 🎬 Director Studio — 3-Stage Pipeline

> จาก **ไอเดีย** สู่ **วิดีโอจริง** ใน 3 ขั้น — AI เขียนบท สร้างคำสั่ง Veo และผลิตวิดีโอ

🌐 **Live demo**: https://directorstudio.sj88ai.com/pipeline/

---

## 📊 ทั้งหมดที่มี (ชิ้นสิ้นครบ)

| Stage | ชื่อ | สถานะ | คำอธิบาย |
|-------|------|------|----------|
| 💡 0 | **Idea** | optional | 1-2 ประโยค |
| 📝 1 | **เขียนบท** | ✅ ชิ้นสิ้น | LLM + 20 production fields/scene |
| 🎬 2 | **คำสั่ง Veo** | ✅ ชิ้นสิ้น | 1 scene = 1 prompt (≤ 1,500 chars) |
| 🎥 3 | **สร้าง VDO** | ✅ ชิ้นสิ้น | Veo 3.1 → MP4 8 วินาที |

## 🌐 Live URLs

| Page | URL | Size | Purpose |
|------|-----|------|---------|
| **Main App** | https://directorstudio.sj88ai.com/ | - | Login + ใช้งานจริง |
| **Pipeline Explainer** | https://directorstudio.sj88ai.com/pipeline/ | 26KB | อธิบาย 3 stages |
| **WOW Manual** | https://directorstudio.sj88ai.com/wow/ | 29KB | Live Demo + 25 screenshots |
| **Sales Page** | https://directorstudio.sj88ai.com/sales/ | 37KB | Pricing + FAQ |
| **Docs** | https://directorstudio.sj88ai.com/docs/ | - | 19 sections + 16 screenshots |
| **Share** | https://directorstudio.sj88ai.com/share/{id} | - | Public project view |

## 🎯 20 Production Fields ต่อ Scene

### Cinematography
- `shot_type` (WS/MS/CU/ECU/OTS/POV)
- `camera_move` (slow dolly in / tilt up / pan / handheld)
- `lens` (24mm wide, 50mm normal, 85mm portrait)
- `duration_sec`

### Atmosphere
- `lighting` (low-key, candlelight, moonlight)
- `mood_color` (deep blue + amber)
- `time_of_day` (02:13, dusk, dawn)
- `weather` (light rain, foggy)

### Sound
- `ambient` (rain on wood, crickets)
- `sfx` (door creak)

### Actor
- `characters_state` (emotion, intensity 6/10, pose)

### Story
- `plot_advances` (discovers letter)
- `foreshadowing` (shadow flickers)

### Production
- `props` (old letter, candle)
- `vfx_notes` (fog overlay, glow)
- `transition_in` (fade from black, 2s)
- `transition_out` (smash cut, fade)

### Director
- `director_note` ("silence is the weapon")
- `pacing` (slow burn, fast, lingering)
- `tone_tags` (#eerie, #romantic, #tense)

## 🔌 API Endpoints

### Stage 1: เขียนบท
```http
POST /api/llm/generate-script
Content-Type: application/json
Authorization: Bearer <jwt>

{
  "prompt": "น้ำตื่นขึ้นมาในห้องมืด ได้ยินเสียงเรียกชื่อตัวเอง",
  "episode_number": 2,
  "num_scenes": 3,
  "style": "Thai horror, dark, atmospheric",
  "previous_episodes": [...]
}
```
Returns: `{ ok, script: { scenes: [{title, action, dialogue, shot_type, camera_move, ...}] } }`

### Stage 2: คำสั่ง Veo (1 scene = 1 prompt)
```http
POST /api/llm/generate-veo-single
Content-Type: application/json
Authorization: Bearer <jwt>

{
  "scene": { id, title, action, dialogue, shot_type, camera_move, lens, lighting, ... },
  "refs": [{slot, display_name, description, url}],
  "project_meta": {genre, language, aspect_ratio, duration_sec},
  "episode_context": {episode_title, episode_logline, previous_scenes_summary},
  "max_chars": 1500
}
```
Returns: `{ veo, prompt_length, max_chars, truncated }`

### Stage 3: สร้าง VDO
```http
POST /api/llm/generate-video
Content-Type: application/json
Authorization: Bearer <jwt>

{
  "project_id": "75a2d0cf09a64504",
  "scene_id": "S01_01",
  "prompt": "ECU shot, slow tilt up, 35mm lens. [ref1] lies on the damp teak floor...",
  "refs": [{slot, url}],
  "aspect_ratio": "9:16",
  "duration_sec": 8
}
```
Returns: `{ job_id, status: "queued" }` → poll `/api/jobs/{id}` or WebSocket

## 🧪 Test Cases

| # | Test | Status | Detail |
|---|------|--------|--------|
| TC-01 | Video Generation | 🟡 4/5 | Step 5 blocked by Veo IP ban (Cloudflare 1010) |
| TC-02 | Script Generation | ✅ 42/42 | 20 fields + UI + 7 meta-blocks |
| TC-03 | Veo Single-Scene | ✅ 57/57 | max 1500 chars + 3 scenes + cross-genre |

Total: **103/106** (97% pass rate)

## 🔑 Key Features

### INGRADAID Mode (commit `512cc28`)
- **Abstract refs**: `ref1`, `ref2`, `ref3` — slots ไม่ใช่ file
- **Reusable across episodes**: ตัวละครเดียวกัน ใช้ EP1-EP10
- **Character consistency**: ตัวเดิมหน้าเดิมทุกคลิป

### Project-Driven Config (commit `b754717`)
- **`project.data.meta`** controls everything:
  - `genre` → drives LLM persona + filters (11 profiles: horror, romance, action, comedy, scifi, ...)
  - `language` → dialogue language (7 profiles: th, en, ja, zh, ko, es, fr)
  - `aspect_ratio` → 9:16 / 16:9 / 1:1
  - `duration_sec` → 8s default
  - `style_guide` → freeform

### Per-Scene Veo Gen (commit `e32028d`)
- 1 scene = 1 prompt (ไม่ batch — คุณภาพดีกว่า)
- Max 1500 chars/scene
- Smart truncation ที่จุด `.`
- Auto-save to `ep.timeline[sceneIdx]`

### LLM JSON Recovery (commit `0acea43`)
- `safe_json_loads()` with 6 strategies
- Handles: truncation, smart quotes, trailing commas
- Real broken output (6057 chars) → recovered

## 🛠️ Tech Stack

### Backend
- **FastAPI** (Python 3.12) — REST API + WebSocket
- **SQLite** (dev) / MySQL (prod-ready) — multi-tenant data
- **Fernet** encryption — per-user Veo JWT + LLM key
- **bcrypt** — password hashing
- **asyncio** — background jobs (DB queue, not Redis)
- **Veo 3.1** via genaipro.io — video generation
- **Claude Sonnet 4.5** (via anthropic-compatible MiniMax-M3) — script + Veo prompts

### Frontend
- **Vanilla ES modules** — no build step
- **HTML5 + CSS3** (CSS variables, grid, flexbox)
- **No framework** (React/Vue) — fast, simple

### Infrastructure
- **Nginx** reverse proxy + SSL (Let's Encrypt)
- **Systemd** service (`director-studio.service`)
- **VPS**: 5.83.147.61 (namnan.co.th)

## 📊 Stats

| Metric | Value |
|--------|-------|
| Production fields/scene | **20** |
| Pipeline stages | **3** (+ optional idea) |
| Genre profiles | **11** |
| Language profiles | **7** |
| Max chars/Veo prompt | **1,500** |
| Reference slots | **3** (ref1/ref2/ref3) |
| Test pass rate | **97%** (103/106) |
| Git commits | **10+** |

## 🚀 Quick Start

### 1. เปิด Director Studio
https://directorstudio.sj88ai.com/

### 2. สมัคร user แรก (ได้ admin อัตโนมัติ)
- Email + password
- Login เข้าระบบ

### 3. ตั้งค่า LLM API key
- ไปที่ **Settings → LLM API Key**
- ใส่ `MiniMax-M3` (anthropic-compatible) key

### 4. ตั้งค่า Veo JWT
- ไปที่ **Settings → Veo JWT**
- ใส่ Veo JWT จาก genaipro.io

### 5. สร้าง Project
- ไปที่ **Projects → + New Project**
- ใส่ title + genre (horror/romance/...) + language (th/en/...)
- อัปโหลด ref1, ref2, ref3 (รูปตัวละคร)

### 6. Generate Episode (AI)
- กด **✨ Generate Episode (AI)**
- ใส่ idea 1-2 ประโยค
- ได้ 3-5 scenes ครบ 20 production fields

### 7. Generate Veo Prompts
- ไปที่ **Script tab** ใน episode
- กดปุ่มเหลือง **🎬 Generate Veo Prompt (1 scene, max 1500 chars)** ทีละ scene
- ได้ Veo prompt + audio_cue + camera

### 8. Generate Video
- ไปที่ **Veo tab**
- กด **🎥 Generate Video**
- รอ 1-3 นาที (background job)
- ได้ MP4 download URL

## 🧪 Run Test Cases

```bash
# TC-01: Video Generation
cd /workspace/director-studio-test-cases/01-video-generation
python3 test_full.py

# TC-02: Script Generation
cd /workspace/director-studio-test-cases/02-script-gen
python3 test_script_gen.py

# TC-03: Veo Single-Scene
cd /workspace/director-studio-test-cases/03-veo-single
python3 test_veo_single.py
```

ทุก test produces:
- `runs/<timestamp>/report.html` — full HTML report
- `runs/<timestamp>/results.json` — machine-readable
- `runs/<timestamp>/screenshots/*.png` — Playwright screenshots

## 📦 Project Structure

```
director-studio/
├── api/                          # FastAPI backend
│   ├── main.py                   # app entry
│   ├── services/
│   │   ├── llm_service.py        # script + veo_prompt_single (20 fields)
│   │   ├── veo_service.py        # Veo 3.1 API client
│   │   └── auth.py               # JWT + bcrypt
│   ├── routes/
│   │   ├── llm.py                # /api/llm/* endpoints
│   │   ├── veo.py                # /api/llm/generate-video
│   │   ├── projects.py
│   │   ├── jobs.py               # async background jobs
│   │   └── ws.py                 # WebSocket
│   ├── jobs/
│   │   ├── queue.py              # DB-backed queue
│   │   └── handlers.py           # script_gen + video_gen handlers
│   └── data/studio.db            # SQLite (multi-tenant)
│
├── www/                          # Frontend (vanilla ES modules)
│   ├── index.html                # main app
│   ├── js/
│   │   ├── episode.js            # render scenes + 7 meta-blocks + per-scene Veo gen
│   │   ├── projects.js
│   │   ├── auth.js
│   │   └── jobs-ui.js
│   ├── style.css
│   ├── pipeline/                 # 🆕 3-Stage explainer
│   │   ├── index.html
│   │   └── screenshots/
│   ├── wow/                      # Live Demo
│   ├── sales/                    # Pricing
│   └── docs/                     # 19 sections
│
└── refs/                         # uploaded character images
```

## 📜 Git History

```
e32028d feat(veo): per-scene single prompt endpoint (max 1500 chars)
0acea43 fix(llm): JSON parse recovery for truncated LLM output
792bd3a feat(veo): use 20 new director fields in Veo prompt generation
8e21ee9 feat(ui): render 20 new director fields in Script tab
05d1ee0 feat(script): 20 new director fields per scene
103efcb fix(models): VeoGenReq accept list[str] or list[dict]
d6ad766 feat(frontend): remove Seed EP1-3 button + better script generation
47d8bcb fix(veo): backward compat for refs param + f-string bug
b754717 feat(INGRADAID c3): genre/language/aspect-agnostic script + Veo
6c4d060 feat(INGRADAID c2): abstract refs (ref1/ref2/ref3)
512cc28 feat(INGRADAID c1): project-level refs + auto-include in Veo
17b1025 feat(B2): Stage 0 Generate Image via GTMage-2
96128b0 Initial commit: Director Studio v2.5
```

## 📅 Timeline

- **2026-07-13 15:00** — v2.5 Initial commit
- **2026-07-13 17:00** — INGRADAID c1-c3 (refs + abstract slots + multi-genre)
- **2026-07-13 19:00** — 20 new director fields
- **2026-07-13 21:00** — UI renders 20 fields
- **2026-07-13 22:00** — Veo uses 20 fields in prompts (4x richer)
- **2026-07-13 23:00** — LLM JSON parse recovery
- **2026-07-14 00:00** — Per-scene Veo gen (1 scene = 1 prompt ≤ 1500)
- **2026-07-14 02:00** — Pipeline explainer page + 3 test cases (103/106 PASS)

## 🐛 Known Limitations

- **Veo JWT IP ban**: VPS IP `5.83.147.61` banned by Cloudflare 1010 — test from local browser only
- **genaipro slow**: image gen 60-180s, sometimes times out
- **LLM JSON parse edge cases**: some prompts with apostrophes still fail
- **Context window 1M**: max_tokens just caps output, not context

## 📝 License

Private project — Director Studio by SJ88
Live: https://directorstudio.sj88ai.com/
GitHub: https://github.com/lnwsj/SJ88-Director-Studio
