You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

15 KiB

DaSiWa API Guide

Полное руководство по использованию DaSiWa I2V/FLF2V API для генерации видео через ComfyUI.


📋 Содержание

  1. Обзор
  2. Аутентификация
  3. Endpoints
  4. Параметры генерации
  5. Примеры использования
  6. Коды ошибок
  7. Best Practices

Обзор

DaSiWa API — асинхронный REST API для генерации видео из изображений с использованием DaSiWa WAN 2.2 TastySin v8.1 моделей через ComfyUI.

Архитектура: Submit → Poll → Retrieve (как RunPod)

Base URL: http://<server_ip>:8080

Аутентификация: HMAC-SHA256 с timestamp и nonce


Аутентификация

Все endpoints (кроме /health) требуют HMAC подписи.

Заголовки запроса

X-Client-Id: <ваш_client_id>
X-Timestamp: <unix_timestamp>
X-Nonce: <случайная_строка_32_символа>
X-Signature: <hmac_sha256_подпись>

Алгоритм подписи

import hmac
import hashlib
import time
import secrets

timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)
body = json.dumps(payload).encode('utf-8')

message = f"{timestamp}.{nonce}.".encode() + body
signature = hmac.new(
    secret_key.encode(),
    message,
    hashlib.sha256
).hexdigest()

Защита от replay-атак

  • Timestamp: запросы старше 5 минут отклоняются
  • Nonce: каждый nonce можно использовать только один раз
  • Signature: уникальна для каждого запроса

Endpoints

GET /health

Health check сервера. Не требует аутентификации.

Response:

{
  "status": "ok",
  "comfyui": "ok",
  "queue": 0,
  "timestamp": 1234567890
}

Поля:

  • status — статус API сервера (ok / error)
  • comfyui — статус ComfyUI (ok / unavailable)
  • queue — количество задач в очереди
  • timestamp — текущее время сервера (unix)

GET /comfyui/status

Детальная проверка статуса ComfyUI. Не требует аутентификации.

Response (ComfyUI доступен):

{
  "comfyui": "ok",
  "ready": true,
  "error": null,
  "timestamp": 1234567890
}

Response (ComfyUI недоступен):

{
  "comfyui": "unavailable",
  "ready": false,
  "error": "Connection failed: Connection refused",
  "timestamp": 1234567890
}

Поля:

  • comfyui — статус (ok / unavailable)
  • ready — готов ли ComfyUI принимать задачи (true / false)
  • error — описание ошибки (если есть)
  • timestamp — текущее время сервера (unix)

Использование: Проверяй этот endpoint перед отправкой задач, чтобы убедиться что ComfyUI запущен.


POST /run

Поставить задачу на генерацию видео в очередь.

Request Body:

{
  "image_base64": "base64_encoded_image_data",
  "prompt": "woman dancing gracefully",
  "negative_prompt": "blurry, low quality",
  "last_image_base64": "base64_encoded_last_frame",
  "width": 528,
  "height": 768,
  "length": 81,
  "steps": 4,
  "cfg": 1.0,
  "seed": -1,
  "fps": 16,
  "sampler_name": "euler",
  "scheduler": "linear_quadratic"
}

Обязательные поля:

  • image_base64 — первый кадр (base64)
  • prompt — текстовое описание

Опциональные поля:

  • last_image_base64 — последний кадр для FLF2V режима
  • negative_prompt — негативный промпт (default: встроенный)
  • width — ширина (default: 528, кратно 16)
  • height — высота (default: 768, кратно 16)
  • length — количество кадров (default: 81)
  • steps — шаги сэмплинга (default: 4)
  • cfg — CFG scale (default: 1.0)
  • seed — сид (-1 = random, default: -1)
  • fps — кадров в секунду (default: 16)
  • sampler_name — сэмплер (default: "euler")
  • scheduler — планировщик (default: "linear_quadratic")

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "IN_QUEUE"
}

Коды ответа:

  • 200 — задача принята
  • 400 — ошибка валидации (нет изображения)
  • 401 — ошибка аутентификации

GET /status/<job_id>

Получить статус задачи.

Response (IN_QUEUE):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "IN_QUEUE"
}

Response (IN_PROGRESS):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "IN_PROGRESS"
}

Response (COMPLETED):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "COMPLETED",
  "output": {
    "video": "base64_encoded_video_data",
    "seed": 42,
    "mode": "I2V",
    "elapsed": 45.2
  }
}

Response (FAILED):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "FAILED",
  "error": "Video generation failed — no output from ComfyUI"
}

Коды ответа:

  • 200 — статус получен
  • 404 — задача не найдена
  • 401 — ошибка аутентификации

POST /purge/<job_id>

Удалить завершённую задачу из памяти сервера (освободить RAM от base64 видео).

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "purged": true
}

Коды ответа:

  • 200 — задача удалена
  • 400 — нельзя удалить активную задачу (IN_QUEUE / IN_PROGRESS)
  • 404 — задача не найдена
  • 401 — ошибка аутентификации

Параметры генерации

Режимы работы

I2V (Image to Video):

  • Генерация видео из одного изображения
  • Передаётся только image_base64

FLF2V (First-Last Frame to Video):

  • Генерация видео между двумя кадрами
  • Передаются image_base64 + last_image_base64

Рекомендуемые значения

Параметр I2V FLF2V Описание
width 528 528 Ширина (кратно 16)
height 768 768 Высота (кратно 16)
length 81 81 Кол-во кадров (~5 сек при 16fps)
steps 4 4 DaSiWa оптимизирован под 4 шага
cfg 1.0 1.0 CFG scale (DaSiWa работает с 1.0)
fps 16 16 Кадров в секунду
sampler_name euler euler Сэмплер
scheduler linear_quadratic linear_quadratic Планировщик

Ограничения

  • Размеры: должны быть кратны 16
  • Length: рекомендуется кратно 8 + 1 (например: 81, 89, 97)
  • Steps: DaSiWa TastySin оптимизирован под 4 шага (можно больше, но медленнее)
  • CFG: значения > 2.0 могут давать артефакты

Примеры использования

Python (с библиотекой requests)

import requests
import base64
import json
import time
from hmac_auth import sign_request

# Загрузка ключей
with open('keys.json') as f:
    keys = json.load(f)

# Подготовка изображения
with open('photo.png', 'rb') as f:
    image_b64 = base64.b64encode(f.read()).decode()

# Payload
payload = {
    "image_base64": image_b64,
    "prompt": "woman dancing gracefully",
    "width": 528,
    "height": 768,
    "length": 81,
    "steps": 4,
    "cfg": 1.0,
    "seed": -1,
    "fps": 16
}

# 1. Submit job
body = json.dumps(payload).encode('utf-8')
auth_headers = sign_request(body, keys['secret_key'], keys['client_id'])
headers = {'Content-Type': 'application/json', **auth_headers}

response = requests.post(
    'http://server:8080/run',
    data=body,
    headers=headers
)
job_id = response.json()['id']
print(f"Job ID: {job_id}")

# 2. Poll status
while True:
    auth_headers = sign_request(b"", keys['secret_key'], keys['client_id'])
    response = requests.get(
        f'http://server:8080/status/{job_id}',
        headers=auth_headers
    )
    data = response.json()
    
    if data['status'] == 'COMPLETED':
        video_b64 = data['output']['video']
        video_bytes = base64.b64decode(video_b64)
        with open('output.mp4', 'wb') as f:
            f.write(video_bytes)
        print(f"Video saved! Seed: {data['output']['seed']}")
        break
    elif data['status'] == 'FAILED':
        print(f"Error: {data['error']}")
        break
    else:
        print(f"Status: {data['status']}")
        time.sleep(5)

# 3. Purge job
auth_headers = sign_request(b"{}", keys['secret_key'], keys['client_id'])
requests.post(
    f'http://server:8080/purge/{job_id}',
    json={},
    headers={'Content-Type': 'application/json', **auth_headers}
)

cURL

# 1. Submit job
curl -X POST http://server:8080/run \
  -H "Content-Type: application/json" \
  -H "X-Client-Id: your_client_id" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Nonce: $(openssl rand -hex 16)" \
  -H "X-Signature: <calculated_signature>" \
  -d '{
    "image_base64": "...",
    "prompt": "woman dancing"
  }'

# Response: {"id": "abc-123", "status": "IN_QUEUE"}

# 2. Check status
curl http://server:8080/status/abc-123 \
  -H "X-Client-Id: your_client_id" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Nonce: $(openssl rand -hex 16)" \
  -H "X-Signature: <calculated_signature>"

# 3. Purge
curl -X POST http://server:8080/purge/abc-123 \
  -H "Content-Type: application/json" \
  -H "X-Client-Id: your_client_id" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Nonce: $(openssl rand -hex 16)" \
  -H "X-Signature: <calculated_signature>" \
  -d '{}'

Коды ошибок

Код Описание Решение
400 Нет входного изображения Передайте image_base64
401 Invalid client ID Проверьте client_id в keys.json
401 Invalid timestamp Синхронизируйте время на клиенте и сервере
401 Nonce already used Replay-атака или дублирующий запрос
401 Invalid signature Проверьте secret_key и алгоритм подписи
404 Job not found Job ID не существует или уже удалён
500 Internal server error Проверьте логи сервера (journalctl -u dasiwa-api)

Best Practices

1. Polling интервал

  • Рекомендуется: 5-10 секунд
  • Не рекомендуется: < 2 секунд (нагрузка на сервер)
  • Генерация обычно занимает 30-60 секунд

2. Timeout

  • Установите timeout на polling: 30 минут (1800 секунд)
  • Если задача не завершилась за это время — проверьте логи сервера

3. Purge после использования

  • Всегда вызывайте /purge/<id> после получения видео
  • Base64 видео занимает ~10-50 MB RAM на сервере
  • Без purge память будет расти

4. Обработка ошибок

try:
    result = wait_for_completion(server, job_id, ...)
except RuntimeError as e:
    if "Timeout" in str(e):
        # Задача зависла — проверьте сервер
        pass
    elif "Job failed" in str(e):
        # Ошибка генерации — проверьте параметры
        pass

5. Retry логика

  • При 401 ошибках — не retry (проблема с ключами)
  • При 500 ошибках — retry с exponential backoff
  • При 404 на /status — задача потеряна, не retry

6. Размер изображений

  • Оптимально: 528x768 или 768x528
  • Большие размеры → больше VRAM → медленнее
  • Маленькие размеры → хуже качество

7. Seed для воспроизводимости

  • Если нужен тот же результат — используйте тот же seed
  • Seed из ответа output.seed — сохраните для повтора

8. Мониторинг очереди

response = requests.get('http://server:8080/health')
queue_size = response.json()['queue']
if queue_size > 5:
    print("Очередь большая, ожидайте дольше")

Лимиты и производительность

Текущие лимиты

  • Одновременные задачи: 1 (1 GPU = 1 задача)
  • Размер очереди: не ограничен (но рекомендуется < 10)
  • Размер изображения: max 2048x2048 (теоретически)
  • Длина видео: max ~300 кадров (ограничено VRAM)

Производительность

Параметры Время генерации VRAM
528x768, 81 frames, 4 steps ~30-45s ~18 GB
768x528, 81 frames, 4 steps ~30-45s ~18 GB
528x768, 161 frames, 4 steps ~60-90s ~24 GB

Время указано для RTX 4090 / A100


Troubleshooting

Задача зависла в IN_PROGRESS

  1. Проверьте логи сервера: journalctl -u dasiwa-api -f
  2. Проверьте ComfyUI: curl http://localhost:8188
  3. Перезапустите сервис: systemctl restart dasiwa-api

Ошибка "Video generation failed"

  • ComfyUI не запущен или недоступен
  • Недостаточно VRAM
  • Workflow файл повреждён

Медленная генерация

  • Проверьте загрузку GPU: nvidia-smi
  • Убедитесь что модели загружены в VRAM (первый запрос медленнее)
  • Уменьшите length или размеры

Changelog

v2.0 (2026-03-07)

  • Асинхронный API (submit + poll)
  • Endpoints: /run, /status, /purge
  • Background worker thread
  • Queue management
  • 🔧 Обновлён на DaSiWa WAN 2.2 TastySin v8.1
  • 🔧 Упрощён workflow (14 нод вместо 50+)

v1.0 (2026-03-06)

  • 🎉 Первый релиз
  • Синхронный /generate endpoint
  • HMAC аутентификация
  • I2V и FLF2V режимы