Десять пробных картинок в ComfyUI делаются парой кликов. Тысяча требует другой схемы: пакетная генерация через очередь, а не через кнопку, скрипт, который ходит в API ComfyUI, по процессу на каждую видеокарту, аренда GPU, когда своих карт мало, и план на брак, который придётся выбросить.
Текст написан по практике: мы гоняем клиентские воркфлоу на объёме, небольшие заказы на своих видеокартах, крупные на арендованных через Vast.ai. Код — обычный Python поверх HTTP-эндпоинтов, которые есть в ComfyUI из коробки.
Batch size или очередь: два вида batch в ComfyUI
Два разных параметра, которые часто путают:
- Batch size — поле
batch_sizeу нодыEmpty Latent Image(от 1 до 4096). Сэмплер обрабатывает все латенты за один проход. - Очередь — счётчик запусков рядом с кнопкой Run или несколько вызовов API. Каждый запуск отдельная задача, ComfyUI выполняет их друг за другом. Загруженные модели остаются в памяти между запусками, пока её хватает, и повторно не грузятся.
| Batch size | Очередь (отдельные запуски) | |
|---|---|---|
| Видеопамять | растёт с каждым латентом; перебор — out of memory | как у одного запуска |
| Скорость | может лучше загрузить GPU на лёгких моделях и малых разрешениях | небольшие накладные на запуск, когда модели уже в памяти |
| Сиды | один сид на всю пачку | свой сид у каждого запуска |
| Повторить одну картинку | тот же сид и batch size или нода LatentFromBatch | перезапуск с её сидом |
| При ошибке | теряется вся пачка | теряется одна картинка |
Строка про сиды важнее, чем кажется. ComfyUI генерирует шум для всей пачки из одного сида, поэтому пятую картинку из пачки в восемь можно повторить только как «сид X, пачка из 8, индекс 4». Когда дойдёт до перегенерации брака, отдельные запуски со своими сидами намного удобнее.
Считайте секунды на одну картинку, а не на запуск. Поднимайте batch size на рабочей карте, пока видеопамять не заполнится или время на картинку не перестанет падать, а объём набирайте очередью. В видео-графах почти всегда один ролик на задачу.
Ловушка: настройка сида control after generate (fixed, increment, randomize) работает только в интерфейсе. Через API сид из JSON используется как есть, менять его должен ваш скрипт.
Промпты из файла, списки сидов и входных картинок
Тысяча запусков с одним промптом и сидом — это одна картинка тысячу раз; ComfyUI и вовсе кэширует одинаковую задачу и не сохраняет новый файл. Объём получается, когда что-то меняется:
- Сиды. Фиксированный список или начальное значение плюс номер задачи, чтобы любой результат можно было повторить.
- Матрица промптов. Объект × стиль × фон: 10 × 5 × 4 — уже 200 комбинаций. Собирайте её скриптом.
- Промпты из файла. В интерфейсе это умеют пакеты кастомных нод, например
Load Prompts From Fileиз Inspire Pack. Для больших запусков скрипт, читающий текстовый файл или CSV, проще контролировать и продолжить после сбоя. - Входные картинки. В графах image-to-image, image-to-video и правки картинки каждый входной файл — отдельная задача. Положите файлы в папку
inputComfyUI (или загрузите черезPOST /upload/image) и подставляйте имя в нодуLoadImage.
Ведите манифест: строка на задачу с промптом, сидом, входом, выходом и статусом. По нему вы продолжите после падения и перегенерируете брак с новыми сидами.
API ComfyUI: запуск воркфлоу скриптом
ComfyUI — веб-сервер, а браузерный интерфейс лишь один из его клиентов. Скрипт может ходить в те же эндпоинты.
- Экспорт в API-формате:
File → Export Workflow (API)(в старых версиях Save (API Format), который появлялся после включения dev mode в настройках). Обычный JSON воркфлоу сервер не примет. В API-формате ключи — id нод сclass_typeиinputs; связь["4", 0]означает выход 0 ноды 4. Выпишите id нод, которые будете менять. - Постановка в очередь:
POST /promptс телом{"prompt": <API JSON>}возвращаетprompt_id. Сломанный граф получит HTTP 400 сnode_errorsещё до очереди. - Ожидание:
GET /history/{prompt_id}отдаёт пустой объект, пока задача не закончилась, потом выходы нод иstatus. Для прогресса откройтеws://host:8188/ws?clientId=<id>и передайте тот жеclient_idв/prompt: придутprogress,executing(сnode: null, когда граф выполнен),execution_successиexecution_error. - Скачивание: у каждого файла есть
filename,subfolderиtype; их передают вGET /view.
Минимальный скрипт: каждая строка prompts.txt с каждым сидом, задачи раскладываются по двум серверам ComfyUI, только стандартная библиотека.
import copy, json, time, urllib.parse, urllib.request
from pathlib import Path
SERVERS = ["127.0.0.1:8188", "127.0.0.1:8189"] # по процессу ComfyUI на видеокарту
PROMPT_NODE, SEED_NODE = "6", "3" # id нод из вашего JSON в API-формате
SEEDS = [1001, 1002, 1003]
workflow = json.loads(Path("workflow_api.json").read_text())
prompts = [p.strip() for p in Path("prompts.txt").read_text().splitlines() if p.strip()]
out = Path("out")
out.mkdir(exist_ok=True)
def call(server, path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(f"http://{server}{path}", data=data,
headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
jobs = []
for i, text in enumerate(prompts):
for seed in SEEDS:
wf = copy.deepcopy(workflow)
wf[PROMPT_NODE]["inputs"]["text"] = text
wf[SEED_NODE]["inputs"]["seed"] = seed
server = SERVERS[len(jobs) % len(SERVERS)]
prompt_id = call(server, "/prompt", {"prompt": wf})["prompt_id"]
jobs.append((server, prompt_id, f"{i:04d}_{seed}"))
for server, prompt_id, tag in jobs:
while not (history := call(server, f"/history/{prompt_id}")):
time.sleep(2)
entry = history[prompt_id]
if entry["status"]["status_str"] != "success":
print("failed:", tag)
continue
for node_output in entry["outputs"].values():
files = [f for v in node_output.values() if isinstance(v, list)
for f in v if isinstance(f, dict) and f.get("type") == "output"]
for f in files:
query = urllib.parse.urlencode({k: f[k] for k in ("filename", "subfolder", "type")})
with urllib.request.urlopen(f"http://{server}/view?{query}") as resp:
(out / f"{tag}_{f['filename']}").write_bytes(resp.read())
6 и 3 — нода промпта и KSampler стандартного воркфлоу ComfyUI; в вашем графе id другие, а у части нод-сэмплеров поле называется noise_seed. Задача, не прошедшая проверку, бросит HTTPError, в теле ответа будут node_errors.
Что мы усвоили на реальных запусках:
- История живёт в памяти процесса ComfyUI. После перезапуска файлы на месте, а связь «задача → файл» потеряна. Пишите
prompt_idв манифест сразу. - Тысячи задач ставьте порциями и отдавайте следующую серверу с самой короткой очередью (
GET /queue). - У ComfyUI нет авторизации. Не открывайте порт наружу, подключайтесь через SSH-туннель или прокси с паролем.
ComfyUI на нескольких видеокартах
Один процесс ComfyUI генерирует на одной видеокарте. Под объём запускайте по процессу на каждую карту, каждый на своём порту:
python main.py --cuda-device 0 --port 8188 --output-directory /data/out0 --temp-directory /data/tmp0
python main.py --cuda-device 1 --port 8189 --output-directory /data/out1 --temp-directory /data/tmp1
--cuda-deviceоставляет процессу видимой только указанную карту.- Папки вывода и временных файлов — свои у каждого процесса: ComfyUI чистит temp при старте и нумерует файлы по содержимому папки вывода, общие папки дают коллизии.
- Папку моделей можно сделать общей, но каждый процесс грузит свою копию моделей в видеопамять и в оперативную память.
С конца мая 2026 года в ComfyUI есть и встроенная нода MultiGPU CFG Split, которая делит одну генерацию между одинаковыми картами. По документации ей нужны одинаковые карты поколения Ampere или новее, она работает с перечисленным набором моделей (среди них WAN 2.2 и SDXL) и ничего не даёт при CFG 1, то есть дистиллированным воркфлоу вроде LoRA типа Lightning не поможет. Она ускоряет одну генерацию; для тысячи картинок отдельные процессы проще, и падение одного не останавливает остальные.
Несколько машин — та же схема с большим числом адресов в SERVERS, если везде одна версия ComfyUI, одни коммиты нод и одни файлы моделей.
ComfyUI в облаке или локально: какие лимиты проверить
Локально вы контролируете всё, но потолок задают одна-две карты. Облачные сервисы с ComfyUI и serverless-GPU снимают вопрос железа и добавляют свои ограничения. Проверьте:
- Кастомные ноды и модели: часто доступен только одобренный набор нод, загрузка своих LoRA может быть ограничена.
- Параллельность: сколько задач на аккаунт идёт одновременно. Это и есть ваша скорость.
- Таймауты: предельное время задачи, в которое упираются длинные видео-графы.
- Холодный старт: на serverless первая задача после простоя грузит модели.
- Единица оплаты: секунды GPU, задачи или кредиты. От неё зависит цена брака.
Аренда целой машины с GPU — середина: любые ноды и модели, но настройка на вас.
ComfyUI на Vast.ai: чему нас научила аренда GPU
Vast.ai — маркетплейс хостов с видеокартами. На крупных заказах мы держим там несколько инстансов параллельно. Вот на чём теряли время:
- Диск задаётся при создании. Увеличить его потом Vast не даёт, а хранение оплачивается, даже когда инстанс остановлен. Модели видео-графа занимают десятки гигабайт; наше правило — примерно полтора объёма всех моделей плюс место под результаты и не меньше 50 ГБ.
- Холодный старт — минуты, и они оплачиваются. Запуск контейнера, установка ComfyUI и кастомных нод, затем скачивание моделей — обычно самая долгая часть, зависящая от сети хоста. Поэтому один инстанс должен брать большую часть запуска.
- Хосты не одинаковые. Наш видео-граф делает апскейл через NVIDIA RTX Video Super Resolution, и на части хостов эта нода не запускалась, хотя CUDA работала. Теперь мы проверяем такие ноды сразу после старта, до скачивания моделей, и при сбое меняем хост. Reliability score у Vast — фильтр, а не гарантия.
- Закрепляйте версии. Кастомные ноды — из git на закреплённых коммитах, ComfyUI — закреплён под каждый воркфлоу. У нас падал загрузчик модели, потому что закреплённый коммит ComfyUI был старше её поддержки. Установка без пинов рано или поздно поменяет результат посреди запуска.
- Исходите из того, что инстанс может пропасть. Выгружайте результаты по ходу работы (мы используем облачное хранилище) и держите манифест отдельно.
Контроль брака на объёме
На тысяче картинок вопрос в том, какая доля негодна и кто её найдёт.
- Сначала пробная партия: 20–50 результатов по всей матрице промптов и входов, а не первые 50 строк. Её мы согласуем с клиентом до массового запуска.
- Посчитайте долю брака. Если негодна каждая пятая, для 1 000 годных генерируйте около 1 250, а худшие промпты перепишите.
- Заморозьте настройки. Смена моделей или параметров посреди запуска — новая пробная партия.
- Отсматривайте глазами: руки и лица, артефакты, сломанный текст, уход персонажа от референса, мерцание и швы в видео. Мы отсматриваем вручную, сеткой, отсортированной по промпту, — плохой промпт виден целым блоком.
- Перегенерируйте брак по манифесту с новыми сидами.
Из чего складывается цена 1 000 генераций
GPU = t × N ÷ (1 − r) ÷ 3600 × P
Итого ≈ GPU + настройка + пробная партия + отсмотр
t — секунды на генерацию, N — сколько нужно годных результатов, r — доля брака, P — цена часа GPU.
tнельзя взять из чужого бенчмарка: оно зависит от модели, разрешения, шагов, графа и карты. Замеряйте на пробной партии.- Несколько видеокарт сокращают время до результата, но не число GPU-часов.
- Настройка — холодные старты, умноженные на число инстансов, плюс часы на установку и отладку. На малых объёмах это главная статья.
- Отсмотр — время человека, оно растёт вместе с
N.
Картинки у нас стоят от $0.10 за штуку на любом чекпойнте и LoRA. Настройка и пробная партия входят в заказ, минимальный заказ $50.
Когда проще отдать нам
Если рабочий воркфлоу у вас есть и нужен объём, а не новое хобби в администрировании GPU, пришлите его нам. Мы разворачиваем шаблон как есть — ноды на закреплённых коммитах, модели с Hugging Face, Civitai или по прямой ссылке, — делаем пробную партию на согласование, гоним объём на своих или арендованных видеокартах, вручную отсматриваем и сдаём архивом или ссылкой на папку. Если модель платная, закрытая или её лицензия запрещает коммерческое использование, скажем до старта (подробнее — о лицензиях моделей с Civitai).
- Ваш воркфлоу на объёме: настройка и массовый запуск воркфлоу ComfyUI
- Картинки на вашем чекпойнте или LoRA: массовая генерация изображений
- Воркфлоу пока не запускается: как запустить воркфлоу с Civitai
Пришлите воркфлоу, задачу и объём через форму заявки.