# RunComfy Serverless API — deployment Wan I2V + smoke test WEBM **Cel:** powtarzalny render `.webm` przy `WAN_LENGTH=33` bez freeze po „Model WAN21 prepared”. --- ## Model integracji (jak pracujemy z RunComfy) Kebabkiller Studio **nie hostuje ComfyUI** i **nie instaluje nodów ręcznie**. Używamy **RunComfy Serverless API** (V2 async queue): | Warstwa | Kto odpowiada | |---------|----------------| | **Deployment GPU** (obraz, modele, custom nodes) | **Zespół RunComfy** — utworzony na podstawie przesłanego [`wan_workflow_api.json`](../backend/src/video/wan_workflow_api.json) | | **Wywołanie inferencji** | **Studio** — `runComfyEngine.js` wysyła pełny `workflow_api_json` per job | | **Polling + download** | **Studio** — `/status`, `/result`, zapis do `backend/output/` | **My Workflows w panelu RunComfy nie są wymagane** — każdy request niesie kompletny graf z backendu. ### Endpoint (V2) ```text POST https://api.runcomfy.net/prod/v2/deployments/{deployment_id}/inference Authorization: Bearer {RUNCOMFY_API_KEY} Body: { "workflow_api_json": { ... } } ``` Dokumentacja API: [RunComfy Serverless — async queue](https://docs.runcomfy.com/serverless/async-queue-endpoints) Obecny deployment (sesja #14): `b36cb944-1eed-4cea-8e63-ef99667db566`. --- ## Co Studio wysyła vs co jest w szablonie Plik [`backend/src/video/wan_workflow_api.json`](../backend/src/video/wan_workflow_api.json) to **źródło prawdy** grafu przekazanego RunComfy przy tworzeniu deploymentu. Przy każdym renderze `buildRunComfyWorkflow()`: - klonuje szablon; - **usuwa node 51** (SaveAnimatedWEBP) — output tylko z **node 52 SaveWEBM**; - nadpisuje: positive/negative (55, 53), rozmiar i `length` (54), seed/steps (56), opcjonalnie klatkę startową base64 (59). Reszta grafu (loadery modeli, WanImageToVideo, KSampler) musi być **zgodna z tym, co RunComfy zbudował na serwerze**. --- ## Dlaczego obecny deployment pada (diagnoza) | Objaw | Interpretacja | |-------|----------------| | Log GPU: freeze po `Model WAN21 prepared` | Problem **środowiska deploymentu**, nie payloadu Studia | | `in_progress` > 10 min, brak `/result` | Hang GPU / zbyt ciężka instancja | | 1× WEBM OK, potem stale | Ten sam deployment — brak powtarzalności | Audyt sesji #12–#13: JSON z Studia był poprawny; bloker po stronie **obrazu deploymentu** (np. zbędne custom nodes poza grafem z `wan_workflow_api.json`). **Fix po stronie RunComfy (nie DIY w Studio):** poprosić zespół RunComfy o **nowy / naprawiony deployment** oparty wyłącznie na aktualnym `wan_workflow_api.json` — minimalny obraz, tylko nody z grafu poniżej. --- ## Wymagane nody (z `wan_workflow_api.json`) Studio oczekuje, że deployment obsługuje te `class_type`: | Node | `class_type` | |------|--------------| | 49, 50 | VAEDecode, VAELoader | | 52 | **SaveWEBM** (output wideo) | | 53, 55 | CLIPTextEncode | | 54 | **WanImageToVideo** | | 56 | KSampler | | 57, 58 | CLIPVisionLoader, CLIPVisionEncode | | 59 | LoadImage (base64 z API lub plik na serwerze) | | 60 | **CLIPLoader** (`type: wan`) | | 61 | **UNETLoader** | | 62 | **ModelSamplingSD3** | **Node 51 (WEBP) nie jest wysyłany** — nie powinien być wymagany do sukcesu. ### Modele (ścieżki w szablonie — RunComfy musi je mieć na deployment) | Plik | Node | |------|------| | `wan_2.1_vae.safetensors` | 50 | | `umt5_xxl_fp8_e4m3fn_scaled.safetensors` | 60 | | `clip_vision_h.safetensors` | 57 | | `wan2.1/wan2.1_i2v_480p_14B_bf16.safetensors` | 61 | Parametry renderu: **480×832**, SaveWEBM **24 fps**, `WAN_LENGTH` domyślnie **33**. --- ## Checklist — po stronie właściciela + RunComfy ### A. Ty (panel RunComfy + Studio) - [ ] Panel RunComfy → deployment `b36cb944…` → **anuluj wiszące requesty** - [ ] Przy nowym deployment ID zaktualizuj `backend/.env`: ```env VIDEO_ENGINE=runcomfy RUNCOMFY_API_KEY=... RUNCOMFY_ENDPOINT=https://api.runcomfy.net/prod/v2/deployments/{DEPLOYMENT_ID}/inference WAN_LENGTH=33 PORT=4001 ``` - [ ] Smoke test CLI (poniżej) - [ ] **Nie commituj** `.env` ### B. Zespół RunComfy (ticket / kontakt) Przekaż im: 1. **Aktualny** [`backend/src/video/wan_workflow_api.json`](../backend/src/video/wan_workflow_api.json) (repo lub export). 2. Prośba: deployment **tylko** z nodów tego grafu + modele z tabeli powyżej — **bez** dodatkowych custom nodes spoza workflow. 3. Objaw: freeze po „Model WAN21 prepared”, brak powtarzalności (1× OK → kolejne joby stale ~10 min). 4. Output: **node 52 SaveWEBM** (WEBM); node 51 nieużywany po stronie klienta. 5. Po utworzeniu: nowy **Inference URL** (V2) → wklejasz do `.env`. Opcjonalnie: poproś o logi ComfyUI z wiszącego joba (czy KSampler startuje po WAN21). ### C. Audyt lokalny (bez GPU — przed smoke) Z katalogu `backend/`: ```bash npm run audit:runcomfy npm run audit:runcomfy -- --json --strict npm run audit:runcomfy -- --live --probe-api --bundle # Git Bash / Linux: ./scripts/audit-runcomfy.sh ``` Sprawdza: `.env`, kontrakt `wan_workflow_api.json`, historię jobów SQLite, pliki `output/`. Opcja `--bundle` zapisuje paczkę (`report.txt` + JSON) do wysłania RunComfy. ### D. Smoke test (GPU) Z katalogu `backend/`: ```bash npm run smoke:runcomfy -- --dry-run # walidacja .env + payload (bez GPU) npm run smoke:runcomfy # jeden render npm run smoke:runcomfy -- --repeat 2 # powtarzalność (2 joby z rzędu) ``` ### E. Kryteria sukcesu | # | Oczekiwanie | |---|-------------| | 1 | POST inference → HTTP 200 + `request_id` | | 2 | Poll: fazy „Ładowanie Wan 2.1 14B” → „Render 33 klatek” | | 3 | Brak błędu `zawieszone (in_progress > 10 min)` | | 4 | `backend/output/smoke-*.webm` (> 10 KB) | | 5 | `--repeat 2`: oba rendery OK | ### F. Smoke przez UI (opcjonalnie) ```bash cd kebabkiller_studio npm run dev ``` Studio → render → `backend/output/{jobId}.webm` --- ## Diagnoza na obecnym deployment (bez nowego ID) 1. Anuluj wiszące joby w panelu RunComfy. 2. `npm run smoke:runcomfy` (jeden raz). 3. Jeśli freeze / stale → **ticket do RunComfy** z punktami z sekcji B (nie zmiana kodu Studia). --- ## Typowe błędy | Błąd | Co zrobić | |------|-----------| | Submit 401/403 | `RUNCOMFY_API_KEY` | | Submit 404 | Zły `RUNCOMFY_ENDPOINT` — Inference URL z Deployments | | `missing node …` w odpowiedzi RunComfy | Deployment niezgodny z `wan_workflow_api.json` → ticket do RunComfy + aktualny JSON | | Wynik tylko WEBP | Deployment zwraca node 51 — upewnij się, że SaveWEBM (52) działa; Studio i tak preferuje WEBM | | WEBM OK raz, potem stale | Nowy / naprawiony deployment od RunComfy (lżejszy obraz) | | Brak klatki startowej | Smoke script wysyła własny JPEG base64; w UI — upload postaci/tła | --- ## Zmienne pollingu (opcjonalnie) ```env # Domyślnie 120×5s ≈ 10 min # RUNCOMFY_POLL_MAX_ATTEMPTS=180 # RUNCOMFY_POLL_INTERVAL_MS=5000 # RUNCOMFY_STALE_AFTER_MS=600000 ``` Dłuższy timeout **nie naprawia** freeze po WAN21 — wtedy problem leży po stronie deploymentu RunComfy. --- ## Powiązane pliki | Plik | Rola | |------|------| | `backend/src/video/wan_workflow_api.json` | Graf przekazany RunComfy + szablon payloadu | | `backend/src/video/runComfyEngine.js` | Serverless: submit / poll / download | | `backend/src/video/runcomfyWorkflowAudit.js` | Kontrakt workflow (audyt) | | `backend/scripts/audit-runcomfy.mjs` | Audyt lokalny (bez GPU) | | `backend/scripts/audit-runcomfy.sh` | Launcher bash | | `backend/scripts/runcomfy-smoke.mjs` | Smoke test | | `backend/.env.example` | Szablon kluczy | --- ## Po udanym smoke 1. Wklej nowy `deployment_id` do handoff. 2. Drugi render z UI — end-to-end. 3. Potem: F1 (plan odcinka) lub wyższe `WAN_LENGTH`.