# Design: Sistem Auto Post AI — Ide → Plan → Naskah → Storyboard → Video → Auto Upload (Shared Hosting)

**Date:** 2026-09-06
**Status:** Draft (menunggu review user sebelum plan implementasi)
**Author:** Sisyphus + brainstorming skill
**Constraint Utama:** Full automatis di dalam **shared hosting** (cPanel PHP + MySQL + Cron). Tidak ada GPU/daemon/Redis. Render berat via API eksternal.

## 1. Ringkasan & Tujuan
Input tunggal `ide` (judul + deskripsi singkat + toggle generatif) → sistem otomatis: generate `plan` → (jika generatif) `naskah` → `storyboard JSON` → `render video` → `jadwal upload` → `publish ke sosmed sesuai jadwal`. User tidak perlu sentuh lagi setelah submit ide.

**Success criteria:**
- 1 ide → 1 video publish tanpa intervensi manual (end-to-end < 30 menit untuk slideshow, < 2 jam untuk generatif).
- Jalan di shared hosting termurah (PHP 8.2, MySQL, cron tiap 5 menit, tanpa SSH root).
- Support YouTube Shorts, TikTok, Instagram Reels, Facebook Reels (OAuth).
- Biaya terkontrol: mode murah slideshow $0.02-0.10/video, mode generatif $0.30-1.00/video.

## 2. Keputusan Arsitektur (Pendekatan A - Rekomendasi)
**Dipilih:** Orkestrator PHP murni di shared hosting + semua AI/render via API eksternal.

**Alternatif ditolak:**
- B Hybrid (hosting + worker eksternal) → melanggar "full di shared hosting".
- C n8n/Make → tidak customizable, biaya, lock-in.

**Prinsip:**
- Shared hosting hanya sebagai **queue + scheduler + dashboard**, bukan renderer.
- Tiap tahap = row di `jobs` dengan polling cron (1 job per tick, hindari timeout 30-120s).
- Semua provider di-abstract via interface `LLMProvider`, `RenderProvider`, `UploadProvider`, `TTSProvider`.

## 3. Arsitektur Komponen

```
[Dashboard PHP (admin)] 
   → POST /api/ideas (ide, is_generative, platforms[], publish_at)
   → DB: projects, ideas, jobs, schedules, uploads, platform_tokens

[Cron 1] cron.php?token=SECRET  */5 * * * *  → Pipeline Orchestrator
[Cron 2] publish.php?token=SECRET */5 * * * * → Publish Scheduler

Orchestrator → LLM (plan) → LLM (naskah) → LLM (storyboard JSON) → Render Router → Video Ready → Scheduler → Uploader
```

**Komponen inti:**
1. **Dashboard** — form ide, list project dengan status warna (pending/running/done/failed), preview plan/naskah/storyboard, log.
2. **Pipeline Orchestrator** (`app/Services/PipelineService.php`) — state machine, buat job berantai.
3. **LLM Service** — OpenAI API (default) fallback Claude. Prompt templated versioned di `prompts/`.
4. **TTS Service** — ElevenLabs / OpenAI TTS.
5. **Render Router** — `if is_generative → Runway/Veo/Luma API` else `Pexels + TTS + FFmpeg lokal (jika ada) atau Shotstack/Creatomate API`.
6. **Scheduler** — `schedules` table (`publish_at`, `platform`, `status`). Cron publish cek `publish_at <= NOW() AND status='scheduled'`.
7. **Uploader** — YouTube Data API v3, TikTok Upload API, Instagram Graph API, Facebook Graph API. Token OAuth encrypted `AES-256`.

**Isolasi & batasan shared hosting:**
- Deteksi FFmpeg saat install: `exec("ffmpeg -version")` → set `RENDER_MODE=local|api_only`.
- Queue tanpa Redis: `SELECT * FROM jobs WHERE status='pending' ORDER BY created_at LIMIT 1 FOR UPDATE`.
- Max 1 job concurrent, timeout per job < 25s, job async (external_id polling) dilanjutkan di tick berikutnya.

## 4. Data Model (MySQL)
- `projects(id, title, idea_raw, is_generative, status, created_at)`
- `jobs(id, project_id, type ENUM('plan','naskah','storyboard','render','upload'), status ENUM('pending','running','done','failed'), payload JSON, result JSON, external_id, attempts, next_retry_at)`
- `storyboards(id, project_id, json JSON, validated BOOLEAN)` — json: `{scenes: [{id, duration, voice_over, visual_prompt, transition, caption}] }`
- `videos(id, project_id, provider, external_id, file_url, local_path, duration, status)`
- `schedules(id, video_id, platform ENUM('youtube','tiktok','instagram','facebook'), publish_at, status, platform_video_id)`
- `platform_tokens(id, platform, access_token_enc, refresh_token_enc, expires_at)`
- `job_logs(id, job_id, level, message, created_at)`
- `settings(key, value)` — API keys, RENDER_MODE, cron token.

## 5. Data Flow Detail
1. User submit ide → create `project` + job `plan`.
2. Cron tick → `plan`: POST LLM prompt → simpan result → create job `naskah` (jika generatif) atau `storyboard`.
3. `naskah`: LLM → output per scene (VO + caption).
4. `storyboard`: LLM → JSON validated via Zod/PHP validator (durasi total = target 30/60s).
5. `render`: call provider async → simpan `external_id` → status `running` → next tick polling `GET /status/{external_id}` hingga `done` → download URL → simpan `videos.file_url`.
6. `schedule`: buat rows di `schedules` per platform dengan `publish_at` (user bisa set interval: misal 1 video/hari jam 19:00).
7. Cron publish → jika `publish_at <= NOW()` → `upload`: call platform API → simpan `platform_video_id` → `status=published` → log.

## 6. Prompt Design (versioned)
- `prompts/plan.v1.txt` — "Kamu produser TikTok, buat plan 3 angle, hook 3 detik, target durasi..."
- `prompts/naskah.v1.txt` — "Dari plan {{plan}}, buat naskah {{scenes}} VO singkat..."
- `prompts/storyboard.v1.txt` — "Output JSON strict..."

Semua prompt simpan versi, bisa A/B test.

## 7. Error Handling & Retry
- Tiap job max 3 retry backoff: 5m, 30m, 2h. `attempts`, `next_retry_at`.
- LLM timeout → retry dengan model fallback.
- Render gagal → tandai `failed`, notifikasi email/Telegram (via `notifications` table).
- Upload gagal karena token expired → refresh OAuth → re-queue job.
- Idempotensi: cek duplikasi `external_id` sebelum create.

## 8. Keamanan
- `cron.php` & `publish.php` wajib `?token=SECRET` (32 char random di `.env`).
- API keys di `settings` encrypted, tidak di repo.
- Upload OAuth state CSRF, token encrypted at rest.
- Validasi storyboard JSON strict, sanitasi input ide (XSS).

## 9. Testing & Observability
- Unit: validator storyboard, prompt renderer, retry backoff.
- Integrasi: mock LLM/Render API.
- Dashboard log per job, dry-run mode (plan/naskah/storyboard tanpa render untuk hemat biaya).
- Health check endpoint `/health` cek DB + token expiry.

## 10. Deployment di Shared Hosting (cPanel)
1. Upload `public/` ke `public_html`, sisanya di luar `public_html`.
2. Set `.env` (DB, API keys, CRON_TOKEN, RENDER_MODE).
3. Import `migrations.sql`.
4. Setup cron: `*/5 * * * * curl -s https://domain.com/cron.php?token=SECRET > /dev/null` dan `*/5 * * * * curl -s https://domain.com/publish.php?token=SECRET`
5. Test deteksi FFmpeg: buka `/admin/system-check`.
6. Hubungkan OAuth sosmed di `/admin/platforms`.

## 11. Estimasi Biaya & YAGNI
- **Dihapus dari v1:** editor video manual, analytics dashboard, multi-user, AI image custom (pakai Pexels dulu).
- **v1 fokus:** 1 ide → 1 video → auto publish. Fitur lain ditunda.

## 12. Open Questions (butuh jawaban user sebelum final plan)
1. Hosting ada FFmpeg? (jika tidak tahu, auto-detect).
2. Platform prioritas v1: YT + TikTok + IG? Atau 1 dulu?
3. Budget per video: slideshow murah vs generatif mahal?
4. Bahasa video: Indonesia saja?
5. Durasi default: 30s atau 60s?

**Next:** Setelah approval spec ini, invoke `writing-plans` skill untuk buat implementation plan terpisah.
