# Fiko Film Stüdyosu - WanGP Köprü Servisi

WanGP'nin (LTX-Desktop-WanGP / Wan2GP) Python in-process API'sini Flutter masaüstü uygulamasının kullanabileceği biçimde **HTTP + Server-Sent Events (SSE)** üzerinden açan FastAPI tabanlı sarmalayıcı servis.

WanGP'nin kendi REST API'si yoktur; bu köprü `shared.api.init()` çağrısı ile WanGP session'ını canlı tutar ve istemcilere oturum başına çoklu üretim işi (job) yürütme imkânı verir.

---

## Mimari Özet

```
┌────────────────────┐         HTTP / SSE          ┌─────────────────────┐
│ Flutter (desktop)  │ ──────────────────────────▶ │ FastAPI Köprü       │
│ fiko_film_studyo   │ ◀── JSON / event-stream ─── │ (uvicorn, port 7861)│
└────────────────────┘                              └──────────┬──────────┘
                                                               │ in-process
                                                               ▼
                                              ┌─────────────────────────────┐
                                              │ WanGP shared.api.WanGPSession│
                                              │ (single, lazy-initialized)  │
                                              └─────────────────────────────┘
```

- **Tek WanGP session**: Model bir kez yüklenir, sonraki işler aynı oturumu paylaşır.
- **Lazy init**: İlk `POST /jobs` isteğine kadar WanGP başlatılmaz.
- **Eşzamanlılık**: WanGP aynı anda yalnızca bir üretim çalıştırabilir (kendi kuralı). Çakışırsa `409 Conflict` döner.
- **Otomatik temizlik**: 1 saatten eski tamamlanmış joblar bellekten otomatik silinir.

---

## Kurulum

### 1. Gereksinimler

WanGP zaten kurulu olmalı: `D:/.../LTX-Desktop-WanGP/Wan2GP/` ve aynı klasörde bir Python venv.

WanGP venv'ine ek olarak HTTP katmanını kuruyoruz:

```bat
set "VENV_PY=D:\__sistem__\Masaustu\FikoYT.Yeni.Cag\video-uretim\ltx-desktop-wangp\LTX-Desktop-WanGP\Wan2GP\env_venv\Scripts\python.exe"
"%VENV_PY%" -m pip install -r requirements.txt
```

`requirements.txt` sadece **fastapi, uvicorn[standard], python-multipart, pydantic** içerir. WanGP venv'i torch / transformers / Pillow vb. zaten içeriyor.

### 2. Çalıştırma

En kolay yol:

```bat
baslat.bat
```

Veya elle:

```bat
"%VENV_PY%" baslat.py --wangp-root "D:\...\Wan2GP" --port 7861
```

#### CLI parametreleri

| Parametre | Varsayılan | Açıklama |
|-----------|------------|----------|
| `--wangp-root` | (zorunlu) | Wan2GP kök klasörü (içinde `shared/api.py` olmalı) |
| `--host`       | 127.0.0.1 | Sadece loopback önerilir |
| `--port`       | 7861      | TCP port |
| `--cikti-dizini` | (boş)   | WanGP üretim çıktı klasörü override |
| `--yukleme-dizini` | `./yuklenenler` | POST /upload hedef klasörü |
| `--reload`     | kapalı    | Geliştirme modu (kod değişince yeniden başlat) |
| `--log-seviye` | info      | debug / info / warning / error |

---

## Endpoint Listesi

### `POST /jobs` - Yeni üretim işi başlat
**Body**:
```json
{
  "settings": {
    "model_type": "hunyuan_1_5_480_t2v",
    "prompt": "Bir kedi piyano çalıyor, sinematik",
    "negative_prompt": "",
    "resolution": "832x480",
    "video_length": 97,
    "num_inference_steps": 30,
    "guidance_scale": 6.0,
    "seed": 42
  },
  "etiket": "deneme_1"
}
```
`settings` doğrudan WanGP'ye gider (free-form). En az `model_type` ve `prompt` zorunludur.

**Yanıt** `200 OK`:
```json
{ "job_id": "8f2e...", "durum": "kuyruk", "olusturma_zamani": 1714766001.234 }
```

**Hata kodları**:
- `400` → `model_type` veya `prompt` eksik
- `409` → WanGP zaten bir iş çalıştırıyor
- `500` → WanGP başlatma hatası

### `GET /jobs?limit=50` - Tüm aktif/son işlerin özeti
```json
[
  { "job_id": "8f2e...", "durum": "calisiyor", "ilerleme": 42, "faz": "inference_stage_1", "model_type": "hunyuan_1_5_480_t2v", ... }
]
```

### `GET /jobs/{job_id}/state` - Anlık durum
```json
{
  "job_id": "8f2e...",
  "durum": "calisiyor",
  "ilerleme": 65,
  "faz": "inference_stage_1",
  "su_anki_adim": 19,
  "toplam_adim": 30,
  "mesaj": "Sample 1/1, Denoising step 19/30",
  "olusturma_zamani": 1714766001.234,
  "baslangic_zamani": 1714766002.111,
  "son_olay_zamani": 1714766050.567
}
```

### `GET /jobs/{job_id}/events` - SSE stream

`text/event-stream` döner. Her event:
```
data: {"kind":"progress","data":{"phase":"inference_stage_1","progress":40,"current_step":12,"total_steps":30,...},"ts":...}

data: {"kind":"preview","data":{"phase":"inference_stage_1","progress":40,"image_b64":"iVBOR...","format":"png"},"ts":...}

data: {"kind":"stream","data":{"stream":"stdout","text":"Loading model..."},"ts":...}

data: {"kind":"completed","data":{"success":true,"generated_files":["D:/.../seg_001/output.mp4"],"errors":[],...},"ts":...}
```

**Olay tipleri**: `started`, `progress`, `preview`, `stream`, `status`, `info`, `output`, `error`, `completed`.
Keepalive: 15 sn boyunca olay gelmezse `: ping\n\n` gönderilir.

### `GET /jobs/{job_id}/result` - Tamamlanmış sonuç
İş `tamam`/`iptal`/`hata` değilse `409` döner.
```json
{
  "job_id": "8f2e...",
  "success": true,
  "generated_files": ["D:/.../output.mp4"],
  "errors": [],
  "cancelled": false,
  "total_tasks": 1,
  "successful_tasks": 1,
  "failed_tasks": 0
}
```

### `POST /jobs/{job_id}/cancel` - İptal et
```json
{ "ok": true, "mesaj": "İptal sinyali gönderildi." }
```

### `DELETE /jobs/{job_id}` - Bellekten sil
Aktif iş ise önce iptal edilir.

### `GET /file?path=<tam-yol>` - Dosya servis et
İçerik tipi MIME tahmini ile, `inline` Content-Disposition ile döner. Üretilen video/görüntü dosyalarını Flutter'da göstermek için.

### `POST /upload` - multipart dosya yükle
**Form-data**: `file=<binary>`
**Yanıt**:
```json
{
  "path": "D:/.../kopru/yuklenenler/1714...filename.png",
  "isim": "filename.png",
  "boyut_byte": 12345,
  "icerik_tipi": "image/png"
}
```
Dönen `path` doğrudan `settings.image_start`, `audio_source` vb. alanlarda kullanılabilir.

### `GET /modeller` - Model kataloğu
WanGP'nin `defaults/*.json` klasörünü tarar. Tip kategorileri: `video_i2v`, `video_t2v`, `video_lipsync`, `image`, `audio_tts`, `postprocess`, `diger`.

```json
[
  { "id": "hunyuan_1_5_480_t2v", "ad": "Hunyuan Video 1.5 Text2Video 480p 8B", "tip": "video_t2v",
    "architecture": "hunyuan_1_5_t2v", "resolution": "832x480", "video_length": 97,
    "num_inference_steps": 30, "guidance_scale": 6.0, "image_outputs": false, ... }
]
```

### `GET /loralar` - LoRA kataloğu
`loras/` klasörünü tarar, `loras_metadata/*.json` ile zenginleştirir.

```json
[
  { "dosya": "D:/.../loras/hunyuan/cinematic_v1.safetensors", "ad": "cinematic_v1",
    "klasor": "hunyuan", "boyut_byte": 268435456, "tetik_kelimeler": ["cinematic"],
    "onerilen_agirlik": 0.85, "aciklama": "..." }
]
```

### `GET /saglik`
```json
{
  "durum": "ok",
  "wangp_yuklu": true,
  "model_aktif": "hunyuan_video_1.5_t2v_bf16.safetensors",
  "aktif_job_sayisi": 1,
  "toplam_job_sayisi": 12,
  "gpu": { "ad": "NVIDIA RTX 4090", "vram_kullanim_mb": 18432.5, "vram_toplam_mb": 24576.0 },
  "versiyon": "1.0.0"
}
```

---

## Örnek curl çağrıları

```bash
# Sağlık kontrolü
curl http://127.0.0.1:7861/saglik

# Modelleri listele
curl http://127.0.0.1:7861/modeller

# Yeni iş başlat
curl -X POST http://127.0.0.1:7861/jobs \
  -H "Content-Type: application/json" \
  -d '{"settings":{"model_type":"flux","prompt":"draw a hat","resolution":"1024x1024"}}'

# Olayları stream et (SSE)
curl -N http://127.0.0.1:7861/jobs/<job_id>/events

# Anlık durum
curl http://127.0.0.1:7861/jobs/<job_id>/state

# Tamamlandığında sonucu al
curl http://127.0.0.1:7861/jobs/<job_id>/result

# İptal
curl -X POST http://127.0.0.1:7861/jobs/<job_id>/cancel

# Dosya yükle (örnek görsel)
curl -X POST http://127.0.0.1:7861/upload -F "file=@./test.png"
```

---

## Sorun Giderme

### `[HATA] WanGP shared.api modülü yüklenemedi`
- `--wangp-root` doğru mu? İçinde `shared/api.py` olmalı.
- WanGP venv kullanıyor musunuz? (sistem Python'unda torch/transformers yoktur)

### `409 Conflict - WanGP session already has a generation in progress`
WanGP aynı anda tek iş çalıştırır. Önceki bitmeden veya `POST /jobs/{id}/cancel` ile iptal edilmeden yeni iş gönderilemez.

### SSE stream'i tarayıcıda 30 sn'de kopuyor
Tarayıcılar varsayılan idle timeout uygular. Köprü 15 sn'de bir keepalive gönderir; ama proxy/CDN arada varsa ona göre ayarlayın.

### Önizleme görüntüsü gelmiyor
WanGP önizleme yalnızca bazı model tipleri için (özellikle video) ve belirli aşamalarda üretilir. Image-only modellerde (FLUX) `preview` event'i nadir / hiç olmaz.

### `model_type` adı hangi değer olmalı?
`GET /modeller` çağrısında dönen `id` alanını kullanın. Bu, `defaults/*.json` dosyasının adına eşittir.

### Loglar nerede?
Konsola yazılır. Servis `--log-seviye debug` ile başlatılırsa daha ayrıntı verir.

---

## Geliştirme Notları

- Flutter masaüstü `package:http` + `package:eventsource` (veya manual `HttpClient` chunk okuma) ile entegre olabilir.
- Üretilen video/görüntü yolu `result.generated_files[0]` — Flutter `GET /file?path=<o-yol>` ile gösterebilir.
- LoRA kullanımı: `settings.activated_loras = ["<full-path-1>", ...]` ve `settings.loras_multipliers = "0.8,1.0"`.
- `image_start`, `image_end`, `audio_source`, `audio_guide` gibi attachment alanlarını `POST /upload` dönen `path` ile doldurun.
