250 lines
8.3 KiB
Markdown
250 lines
8.3 KiB
Markdown
# 🎬 DaSiWa API Server для ComfyUI
|
||
|
||
Автономный API сервер для генерации видео через ComfyUI на выделенном GPU сервере (Intelion Cloud и т.д.).
|
||
|
||
**Безопасность:** HMAC подпись каждого запроса (timestamp + nonce + body). Перехват бесполезен — подпись уникальна.
|
||
|
||
---
|
||
|
||
## 📁 Структура
|
||
|
||
```
|
||
custom_comfyui/
|
||
├── server.py # API сервер (ставится на GPU машину)
|
||
├── client.py # Клиент (запускается на твоём ПК)
|
||
├── hmac_auth.py # HMAC авторизация (нужен и там, и там)
|
||
├── generate_keys.py # Генерация ключей (один раз)
|
||
├── setup.sh # Автоустановка: Python, зависимости, UFW, systemd
|
||
├── dasiwa-api.service # Systemd сервис (автозапуск)
|
||
├── requirements.txt # Python зависимости
|
||
├── keys.json # 🔒 Ключи (НЕ коммитить!)
|
||
└── workflow_api.json # 🎨 ComfyUI workflow (DaSiWa WAN 2.2 Lightspeed)
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Быстрый старт
|
||
|
||
### 1. Загрузка моделей на сервер
|
||
|
||
```powershell
|
||
$SERVER = "user@<ip_сервера>"
|
||
|
||
# HIGH checkpoint (~13 GB)
|
||
scp "DasiwaWAN22I2V14BLightspeed_synthseductionHighV9.safetensors" ${SERVER}:/ComfyUI/models/checkpoints/
|
||
|
||
# LOW checkpoint (~13 GB)
|
||
scp "DasiwaWAN22I2V14BLightspeed_synthseductionLowV9.safetensors" ${SERVER}:/ComfyUI/models/checkpoints/
|
||
|
||
# VAE (~335 MB)
|
||
scp "wan_2.1_vae.safetensors" ${SERVER}:/ComfyUI/models/vae/
|
||
|
||
# Text Encoder (~9.4 GB, fp16 - required for Lightspeed models)
|
||
scp "umt5_xxl_fp16.safetensors" ${SERVER}:/ComfyUI/models/text_encoders/
|
||
```
|
||
|
||
**Скачать модели:**
|
||
- **Checkpoints:** [DaSiWa WAN 2.2 i2v 14B (S) Lightspeed](https://civitai.com/models/1981116)
|
||
- **VAE:** [wan_2.1_vae.safetensors](https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/blob/main/split_files/vae/wan_2.1_vae.safetensors)
|
||
- **Text Encoder:** [umt5_xxl_fp16.safetensors](https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp16.safetensors) (fp16 required for Lightspeed models)
|
||
|
||
**Структура моделей на сервере:**
|
||
```
|
||
📂 ComfyUI/models/
|
||
├── checkpoints/
|
||
│ ├── DasiwaWAN22I2V14BLightspeed_synthseductionHighV9.safetensors
|
||
│ └── DasiwaWAN22I2V14BLightspeed_synthseductionLowV9.safetensors
|
||
├── vae/
|
||
│ └── wan_2.1_vae.safetensors
|
||
└── text_encoders/
|
||
└── umt5_xxl_fp16.safetensors
|
||
```
|
||
|
||
### 2. Генерация ключей (на любом ПК с Python)
|
||
|
||
```bash
|
||
cd custom_comfyui
|
||
python generate_keys.py
|
||
```
|
||
|
||
Появится файл `keys.json`. **Нужен и на сервере, и на клиенте.**
|
||
|
||
### 3. Загрузка на сервер
|
||
|
||
```powershell
|
||
# С Windows на Ubuntu сервер
|
||
$SERVER = "root@<ip_сервера>"
|
||
|
||
# Загрузить всю папку
|
||
scp -r custom_comfyui/ ${SERVER}:/root/
|
||
|
||
# ИЛИ по файлам
|
||
scp server.py hmac_auth.py generate_keys.py setup.sh requirements.txt keys.json workflow_api.json ${SERVER}:/root/custom_comfyui/
|
||
```
|
||
|
||
### 4. Установка на сервере (одна команда)
|
||
|
||
```bash
|
||
ssh root@<ip_сервера>
|
||
cd /root/custom_comfyui
|
||
chmod +x setup.sh
|
||
sudo ./setup.sh
|
||
```
|
||
|
||
Скрипт автоматически:
|
||
- ✅ Установит Python, pip, wget
|
||
- ✅ Установит Python зависимости
|
||
- ✅ Настроит Firewall (открыт 22 + 8080, закрыт 8188)
|
||
- ✅ Создаст systemd сервис с автозапуском
|
||
- ✅ Сгенерирует ключи (если нет)
|
||
|
||
### 5. Скопируй keys.json на свой ПК
|
||
|
||
```powershell
|
||
scp root@<ip_сервера>:/root/custom_comfyui/keys.json .
|
||
```
|
||
|
||
Положи в папку `custom_comfyui/` на своём ПК.
|
||
|
||
### 6. Проверка
|
||
|
||
```bash
|
||
# На сервере:
|
||
curl http://localhost:8080/health
|
||
|
||
# Ответ:
|
||
# {"comfyui": "ok", "status": "ok", "queue": 0, "timestamp": 1234567890}
|
||
```
|
||
|
||
### 7. Генерация видео (с клиента)
|
||
|
||
```bash
|
||
cd custom_comfyui
|
||
|
||
# I2V — из одного изображения
|
||
python client.py \
|
||
--server http://<ip_сервера>:8080 \
|
||
--image photo.png \
|
||
--prompt "woman dancing gracefully" \
|
||
--output video.mp4
|
||
|
||
# FLF2V — из двух кадров
|
||
python client.py \
|
||
--server http://<ip_сервера>:8080 \
|
||
--image start.png \
|
||
--last-image end.png \
|
||
--prompt "smooth transition between poses" \
|
||
--output transition.mp4
|
||
```
|
||
|
||
Клиент работает асинхронно (как RunPod): отправляет задачу → поллит статус → забирает видео.
|
||
|
||
---
|
||
|
||
## 🔄 API Endpoints (асинхронный, как RunPod)
|
||
|
||
| Endpoint | Method | Описание |
|
||
|----------|--------|----------|
|
||
| `/run` | POST | Поставить задачу в очередь → `{"id": "...", "status": "IN_QUEUE"}` |
|
||
| `/status/<id>` | GET | Получить статус: `IN_QUEUE` / `IN_PROGRESS` / `COMPLETED` / `FAILED` |
|
||
| `/purge/<id>` | POST | Удалить задачу из памяти (освободить RAM) |
|
||
| `/health` | GET | Health check (без авторизации) |
|
||
|
||
**Пример потока:**
|
||
```
|
||
1. POST /run {image_base64: "...", prompt: "..."} → {id: "abc-123", status: "IN_QUEUE"}
|
||
2. GET /status/abc-123 → {id: "abc-123", status: "IN_PROGRESS"}
|
||
3. GET /status/abc-123 → {id: "abc-123", status: "COMPLETED", output: {video: "base64...", seed: 42, ...}}
|
||
4. POST /purge/abc-123 → {id: "abc-123", purged: true}
|
||
```
|
||
|
||
---
|
||
|
||
## ⚙️ Параметры генерации
|
||
|
||
| Параметр | По умолчанию | Описание |
|
||
|----------|-------------|----------|
|
||
| `--width` | 528 | Ширина (кратно 16) |
|
||
| `--height` | 768 | Высота (кратно 16) |
|
||
| `--length` | 81 | Кол-во кадров (~5 сек при 16fps) |
|
||
| `--steps` | 4 | Шаги (DaSiWa оптимизирован под 4) |
|
||
| `--cfg` | 1.0 | CFG scale (DaSiWa работает с 1.0) |
|
||
| `--seed` | -1 | Сид (-1 = рандом) |
|
||
| `--fps` | 16 | Кадров в секунду |
|
||
|
||
---
|
||
|
||
## 🔐 Как работает безопасность
|
||
|
||
```
|
||
Клиент:
|
||
1. Берёт тело запроса (JSON)
|
||
2. Создаёт timestamp + nonce (случайная строка)
|
||
3. Подписывает: HMAC-SHA256(secret_key, timestamp.nonce.body)
|
||
4. Отправляет: body + заголовки (client_id, timestamp, nonce, signature)
|
||
|
||
Сервер:
|
||
1. Проверяет client_id
|
||
2. Проверяет timestamp (не старше 5 минут)
|
||
3. Проверяет nonce (не использован ранее — защита от replay)
|
||
4. Вычисляет подпись и сравнивает
|
||
5. Если всё ОК — выполняет запрос
|
||
```
|
||
|
||
**Почему это безопасно:**
|
||
- Без secret_key нельзя создать валидную подпись
|
||
- Каждый запрос уникален (nonce) — replay-атака невозможна
|
||
- Timestamp — протухшие запросы отклоняются
|
||
- secret_key **никогда** не передаётся по сети
|
||
|
||
---
|
||
|
||
## 🔧 Управление
|
||
|
||
```bash
|
||
# Статус API
|
||
systemctl status dasiwa-api
|
||
|
||
# Перезапуск
|
||
systemctl restart dasiwa-api
|
||
|
||
# Логи (live)
|
||
journalctl -u dasiwa-api -f
|
||
|
||
# Стоп
|
||
systemctl stop dasiwa-api
|
||
```
|
||
|
||
---
|
||
|
||
## 🔥 Firewall
|
||
|
||
Открытые порты:
|
||
- **22** — SSH
|
||
- **8080** — API (Python напрямую)
|
||
|
||
Закрытые:
|
||
- **8188** — ComfyUI UI (только localhost)
|
||
|
||
---
|
||
|
||
## ❓ Troubleshooting
|
||
|
||
**ComfyUI недоступен:**
|
||
```bash
|
||
# Проверь что ComfyUI запущен
|
||
curl http://localhost:8188
|
||
# Посмотри процесс
|
||
ps aux | grep comfy
|
||
```
|
||
|
||
**API не отвечает:**
|
||
```bash
|
||
journalctl -u dasiwa-api -n 50
|
||
systemctl restart dasiwa-api
|
||
```
|
||
|
||
**Ошибка авторизации (401):**
|
||
- Проверь что `keys.json` одинаковый на клиенте и сервере
|
||
- Проверь время на обоих машинах (`date` на сервере, часы на ПК)
|