No description
  • Python 70.8%
  • TypeScript 20.1%
  • CSS 4.6%
  • PowerShell 2%
  • Shell 1.8%
  • Other 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
openhands 1c64e093f2
All checks were successful
Build ComfyUI-OpenAI-API image / build-and-push (push) Successful in 2m14s
Add POST /v1/videos/extensions + POST /v1/videos/{id}/remix (OpenAI-compat)
Both create a new video job derived from a completed source video, sharing
one builder (_create_derived_video_job) plus _load_completed_source_video
(404 not found / 409 not complete) and _parse_video_derivation_payload
(JSON or multipart).

POST /v1/videos/extensions:
- body: prompt (required) + video:{id} (JSON) or video.id (form) reference
- inherits the source's model/seconds/size/quality unless the request
  overrides them; kind follows the source (or img2video if an image ref is
  supplied); records extended_from in job metadata
- returns a queued Video object with remixed_from_video_id pointing at the
  source

POST /v1/videos/{video_id}/remix:
- body: prompt (required); same inheritance as extensions
- re-runs the source workflow with the new prompt; records remixed_from in
  metadata; returns queued Video object with remixed_from_video_id

Route order verified: /v1/videos/extensions (POST) registers before
/v1/videos/{video_id} (GET) so it is not shadowed; {video_id}/remix is a
distinct suffix. 8 new tests (extension: 400 no-prompt/no-ref, inherit
model+seconds+size+quality, seconds override wins, 409 incomplete source;
remix: new job w/ new prompt + inherited seconds, 400 no-prompt, 404
unknown source). 180 tests green. README: curl examples for both.
2026-09-29 18:20:13 +00:00
.forgejo/workflows i18n: language dropdown + EN fallback + dynamic language discovery 2026-09-29 09:28:58 +00:00
.github/workflows Fix desktop navigation and shutdown 2026-05-30 01:23:59 +08:00
assets Add application icon to packaged executables 2026-05-30 19:41:06 +08:00
comfyui-api-workflows z_image_int8_params 2026-08-26 20:44:28 +08:00
frontend Add ErrorBoundary: a view crash shows a panel, not a blank window 2026-09-29 15:54:34 +00:00
i18n i18n: language dropdown + EN fallback + dynamic language discovery 2026-09-29 09:28:58 +00:00
packaging 跨平台脚本 2026-08-24 14:52:04 +08:00
scripts 跨平台脚本 2026-08-24 14:52:04 +08:00
src/comfyui2api Add POST /v1/videos/extensions + POST /v1/videos/{id}/remix (OpenAI-compat) 2026-09-29 18:20:13 +00:00
tests Add POST /v1/videos/extensions + POST /v1/videos/{id}/remix (OpenAI-compat) 2026-09-29 18:20:13 +00:00
.dockerignore ComfyUI-OpenAI-API (Variant B): opq007 base + Workflow Studio + graph-seed randomization + Russian i18n + Docker/CI/Compose 2026-09-27 18:29:43 +00:00
.env.example ComfyUI-OpenAI-API (Variant B): opq007 base + Workflow Studio + graph-seed randomization + Russian i18n + Docker/CI/Compose 2026-09-27 18:29:43 +00:00
.gitignore Add ErrorBoundary: a view crash shows a panel, not a blank window 2026-09-29 15:54:34 +00:00
AGENTS.md i18n: language dropdown + EN fallback + dynamic language discovery 2026-09-29 09:28:58 +00:00
docker-compose.yml Rebrand image paths akalagov -> maydayoffice after repo transfer 2026-09-28 06:17:38 +00:00
docker-entrypoint.sh Fix: mapping save 500 on non-writable ./workflows (uid mismatch) 2026-09-28 10:06:21 +00:00
Dockerfile i18n: language dropdown + EN fallback + dynamic language discovery 2026-09-29 09:28:58 +00:00
LICENSE Add MIT License to the project 2026-03-22 17:32:14 +08:00
pyproject.toml Add desktop dashboard and Windows release workflow 2026-05-30 00:05:32 +08:00
README.md Add POST /v1/videos/extensions + POST /v1/videos/{id}/remix (OpenAI-compat) 2026-09-29 18:20:13 +00:00
README.upstream-zh.md ComfyUI-OpenAI-API (Variant B): opq007 base + Workflow Studio + graph-seed randomization + Russian i18n + Docker/CI/Compose 2026-09-27 18:29:43 +00:00
requirements.txt Switch project management to uv 2026-03-22 20:35:38 +08:00
start.bat Improve job failure reporting and add launcher scripts 2026-03-16 00:21:28 +08:00
start.ps1 参数匹配 2026-08-22 10:47:53 +08:00
start.sh remote serve 2026-08-25 10:41:00 +08:00
uv.lock Switch project management to uv 2026-03-22 20:35:38 +08:00

🚀 ComfyUI-OpenAI-API

ComfyUI → OpenAI-совместимый HTTP API: генерация картинок и видео по запросам /v1/images/generations, /v1/images/edits, /v1/videos/* — как будто вы обращаетесь к любой OpenAI-совместимой модели.

Docker CI Registry Made with OpenHands

Upstream: GitHub Stars GitHub Forks GitHub Issues Last Commit

This repo: Forgejo Last Commit Forgejo Issues Open Forgejo Issues Closed

Этот репозиторий — «Вариант B»: зрелая база opq007/Comfyui2api (мультибэкенд, SQLite, job-планировщик) + Workflow Studio из форка RzMY + графовая рандомизация seed из форка xundaoai + русский дашборд + Docker/CI/Compose инфраструктура maydayoffice.

Исходный (китайский) README upstream сохранён в README.upstream-zh.md.


✨ Что даёт

  • 🎨 Мультимодальность: text-to-image / image-to-image / text-to-video / image-to-video — всё определяется capability-анализом workflow (KSampler / VideoHelperSuite и т.д.), а не настройками.
  • 🖥️ Несколько ComfyUI-бэкендов: инстансы регистрируются в веб-панели (раздел «Инстансы»), хранятся в SQLite. У каждого: URL, health-check, лимит параллельных слотов, стратегия маршрутизации (round-robin / random / failover), привязка к опубликованным моделям.
  • 🌐 Публикуемые модели: вы сами решаетите, какие workflow становятся «моделями» (slug + capability), а какие остаются внутренними.
  • ⚙️ Workflow Studio: загрузка workflow (drag-n-drop или выбор файла), автообнаружение полей (prompt / negative / steps / cfg / size / seed / image), редактор маппинга (JSON-sidecar .comfyui2api/*.params.json), онлайн-тест генерации прямо из панели с живым предпросмотром.
  • 🎲 Рандомизация seed: даже если workflow не объявляет seed параметром, граф-обход пересажает noise_seed/seed/seed2 на KSampler / SamplerCustom / SamplerCustomAdvanced / RandomNoise. Явный seed в запросе уважается (репродуктивность).
  • 🔁 Hot-reload: изменения в каталоге workflow подхватываются без рестарта.
  • 📡 Realtime-прогресс: WebSocket ComfyUI → события узла/прогресса → task.progress_percent + SSE/поллинг в панели.
  • 🔐 Fail-closed: API требует API_TOKEN, админка /ui — ADMIN_TOKEN. Брутфорс админки блокируется по IP (rate-limit).
  • 🪶 Совместимость с New-API / один клик к любому OpenAI-клиенту: base_url=https://ваш-хост:8000/v1, model=<slug>, Authorization: Bearer <API_TOKEN>.

📡 Быстрый старт (Docker)

git clone https://git.maydayoffice.kz/maydayoffice/ComfyUI-OpenAI-API
cd ComfyUI-OpenAI-API
cp .env.example .env
# отредактируйте .env: API_TOKEN и ADMIN_TOKEN (минимум)
docker compose up -d

Откройте http://localhost:8000/ui → введите ADMIN_TOKEN → добавьте инстанс ComfyUI (http://host.docker.internal:8188 или внешний адрес) → создайте публикуемую модель из загруженного workflow → попробуйте через Playground.

Готовый образ: git.maydayoffice.kz/maydayoffice/comfyui-openai-api:latest (собирается Forgejo CI при пуше в main, см. .forgejo/workflows/ci-cd.yml).

Проблема с правами на ./workflows. Контейнер работает от непривилегированного пользователя appuser (uid 10001). Входная точка образа (docker-entrypoint.sh) при старте как root делает chown -R /data в 10001, а потом снижает права через setpriv — поэтому bind-монтаж ./workflows (даже если на хосте он принадлежит другому uid) становится записываемым. Если вы запускаете старый образ без этого фикса и «Сохранить и перезагрузить» / загрузка workflow молча не работают (в логах PermissionError, HTTP 500), вручную выполните на хосте: sudo chown -R 10001:10001 ./workflows — либо пересоберите/перетяните свежий образ.


🔌 OpenAI-совместимый API

Text-to-image

curl -s -X POST http://localhost:8000/v1/images/generations \
  -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "model": "my-t2i",
    "prompt": "a red paper boat on calm water, cinematic",
    "n": 1,
    "size": "1024x1024",
    "quality": "high",
    "response_format": "b64_json"
  }'

Image-to-image

curl -s -X POST http://localhost:8000/v1/images/edits \
  -H "Authorization: Bearer $API_TOKEN" \
  -F "model=my-i2i" -F "prompt=make it night" \
  -F "image=@input.png" \
  -F "strength=0.5"

Image variations (prompt не требуется — вариация по картинке)

# multipart (как в OpenAI) или JSON-тело с image: data-URL / URL
curl -s -X POST http://localhost:8000/v1/images/variations \
  -H "Authorization: Bearer $API_TOKEN" \
  -F "model=my-i2i" -F "image=@input.png" -F "n=2"

Video (если workflow — video-capable)

curl -s -X POST http://localhost:8000/v1/videos \
  -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"my-t2v","prompt":"sunset over the sea","size":"1280x720"}'

Поле model — это slug публикуемой модели (см. раздел «Публикуемые модели» в /ui), а не имя workflow напрямую.

Video edits — по уже готовому видео (OpenAI video.id)

# JSON: ссылка на завершённую видео-задачу (id из POST /v1/videos)
curl -s -X POST http://localhost:8000/v1/videos/edits \
  -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"my-i2v","prompt":"make it darker","video":{"id":"video_<job_id>"}}'

# или multipart: прямая загрузка видеофайла / ссылки
curl -s -X POST http://localhost:8000/v1/videos/edits \
  -H "Authorization: Bearer $API_TOKEN" \
  -F "model=my-i2v" -F "prompt=make it darker" -F "video=@take.mp4"

Задачей-источником может быть только завершённое видео (иначе 409). Отвечает как POST /v1/videos — объект video со status: "queued"; результат — через GET /v1/videos/{id} и GET /v1/videos/{id}/content.

Video extension — продолжить готовое видео

# prompt описывает продолжение; model/seconds/size наследуются от исходника
# (переопределяются полями запроса), video.id — ссылка на завершённую задачу
curl -s -X POST http://localhost:8000/v1/videos/extensions \
  -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
  -d '{"prompt":"the camera pans right","video":{"id":"video_<job_id>"}}'

Video remix — перегенерировать с новым prompt

# тот же workflow/модель, но новый prompt; остальные параметры наследуются
curl -s -X POST http://localhost:8000/v1/videos/video_<job_id>/remix \
  -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
  -d '{"prompt":"now in black and white"}'

Оба эндпоинта отвечают объектом video (status:"queued") с полем remixed_from_video_id, указывающим на источник. Результат — через GET /v1/videos/{id} и /content.

Видео: запрос статуса, скачивание, список, удаление

# Статус одной задачи (id — из ответа POST /v1/videos)
curl -s http://localhost:8000/v1/videos/{video_id} \
  -H "Authorization: Bearer $API_TOKEN"

# Готовый файл (только когда status=completed; URL также возвращается в поле url)
curl -s -o result.mp4 http://localhost:8000/v1/videos/{video_id}/content \
  -H "Authorization: Bearer $API_TOKEN"

# Список видео-задач (limit до 100, after — курсор: video_id, вернёт старшие по времени)
curl -s "http://localhost:8000/v1/videos?limit=10" \
  -H "Authorization: Bearer $API_TOKEN"

# Удалить задачу: из памяти, из SQLite и с диска (runs/{job_id}/)
curl -s -X DELETE http://localhost:8000/v1/videos/{video_id} \
  -H "Authorization: Bearer $API_TOKEN"

Параметры (стандартный набор)

prompt, negative_prompt, model, n, size/width/height, steps, scheduler, cfg, seed, quality, seconds/frames/fps (видео), strength (i2i), response_format (url | b64_json), произвольные extra_body-поля, проксируемые в маппинг.


📂 Структура каталогов (в контейнере)

Mount Path Содержимое
./workflows /data/workflows ComfyUI API JSON (.json) + sidecar-маппинг (.comfyui2api/*.params.json)
volume /data/runs Результаты задач (картинки/видео)
volume /data/data SQLite: задачи, инстансы, модели
(в образе) /opt/webui Собранная версия дашборда (язык переключается в рантайме)
(в образе) /app/i18n apply_i18n.py + locales/*.json (проверка/повторный перевод после merge upstream)

WORKFLOWS_DIR, RUNS_DIR, DATA_DIR, DATABASE_PATH, COMFYUI2API_UI_DIST_DIR уже заданы в ENV образа; переопределять не нужно (кроме случаев, когда вы знаете, зачем).


🧑‍💻 Workflow Studio (раздел «Workflow» в /ui)

  1. Upload — файл workflow (ComfyUI → File → Export (API)), либо drag-n-drop. Имя файла = имя workflow.
  2. Detected fields — автообнаруженные кандидаты (prompt / negative / steps / cfg / seed / width / height / image).
  3. Mapping — привяжите стандартные API-параметры к полям графа (через UI или raw JSON). Результат пишется в sidecar .comfyui2api/<workflow>.params.json и hot-reload'ится.
  4. Test — inline-запуск тестовой генерации с прогрессом и предпросмотром результата (для txt2img / img2img без image-ввода).

Все операции Studio идут через админ API /v1/admin/workflows* (POST upload, GET details, PUT/DELETE mapping, DELETE workflow, POST test).


🎲 Рандомизация seed

Дополнение к spec-based обработке (upstream random'ит seed, только если workflow объявил его параметром): граф-обход randomize_graph_noise_seeds() в jobs.py пересажает noise_seed / seed / seed2 на узлах KSampler, SamplerCustom, SamplerCustomAdvanced, RandomNoise для каждого job.

Гвард: если клиент прислал seed явно (в standard_params), граф не трогается — повторный запрос с тем же seed вернёт тот же результат.

Тесты: tests/test_seed_randomize.py (4 кейса).


🔌 Админ API (/v1/admin, токен ADMIN_TOKEN)

Метод Путь Назначение
GET /v1/admin/overview статистика, конфиг (без секретов)
GET/POST/PUT/DELETE /v1/admin/instances[/{slug}] бэкенды
GET/POST/PUT/DELETE /v1/admin/models[/{slug}] публикуемые модели
GET /v1/admin/workflows список workflow
POST /v1/admin/workflows upload (Studio)
GET /v1/admin/workflows/{name} details + fields + suggested template (Studio)
PUT/DELETE /v1/admin/workflows/{name}/mapping маппинг (Studio)
DELETE /v1/admin/workflows/{name} удаление workflow (Studio)
POST /v1/admin/workflows/{name}/test inline-тест (Studio)
GET/POST /v1/admin/tasks[/{id}] журнал задач
GET /v1/admin/tasks/{id}/outputs результаты
POST /v1/admin/shutdown остановить сервис

📄 Конфигурация

Все параметры — в .env.example (скопировать в .env). Минимум:

API_TOKEN=...          # обязателен
ADMIN_TOKEN=...        # обязателен
API_PORT=8000

Полный список (опциональные): PUBLIC_BASE_URL, SIGNED_URL_SECRET, JOB_RETENTION_SECONDS, MAX_JOBS_IN_MEMORY, TIMEOUT_S, HTTP_TIMEOUT_S, HEALTH_CHECK_*, лимиты и т.д.


🐳 Сборка образа (CI)

  • Forgejo: .forgejo/workflows/ci-cd.yml. Триггеры: push в main + ручной (workflow_dispatch с commit / force).
  • Образ: git.maydayoffice.kz/maydayoffice/comfyui-openai-api:{sha-7,full,latest}.
  • Этапы: 1) node:20-alpine + pnpm 8: pnpm install --frozen-lockfile → python3 i18n/apply_i18n.py frontend (проверка покрытия: каждый словарь locales/<code>.json имеет тот же набор ключей, что en.json, каждый ключ t("msg_N") есть во всех словарях, params совпадают с {placeholder}'ами — иначе падает build) → pnpm build (tsc --noEmit && vite build). Перевод происходит в рантайме (в браузере): все словари frontend/src/lib/locales/*.json подхватываются через import.meta.glob и попадают в бандл; в коде — только семантические ключи msg_N, никакого пользовательского текста. Недостающий ключ автоматически показывается на английском (fallback en). 2) python:3.11-slim: pip install . + /opt/webui + ENV + appuser.
  • Перед сборкой CI гоняет python -m unittest discover -s tests в эфемерном контейнере python:3.11-slim — ровно то, что потом окажется в образе.

🧬 Upstream / forks — что взято от кого

Комитет Источник Что
База opq007/Comfyui2api 3e69d6f мультибэкенд, SQLite store, job scheduler, instance pool, admin limiter, signed URLs, multi-backend routing
Workflow Studio RzMY/Comfyui2api 9c3f110 загрузка workflow из UI, fields, mapping editor, inline test; перенесён модульно (merge не чистый — 15 конфликтов)
Граф-рандом seed xundaoai/Comfyui2api _randomize_noise_seeds() на KSampler/SamplerCustom/RandomNoise, адаптирован под нашу fail-soft модель (не трогает явный seed)
i18n + Docker/CI/Compose maydayoffice/ComfyUI2API (Вариант A) runtime i18n на семантических ключах с динамическим набором языков: i18n/apply_i18n.py (coverage-верификатор, авто-обнаруживает locales/*.json) + словари frontend/src/lib/locales/{en,ru,zh}.json (~286 ключей, en — fallback, новые языки добавляются без правки кода), Dockerfile (multi-stage), .forgejo/workflows/ci-cd.yml, docker-compose.yml, .env.example, .dockerignore
Лицензия MIT (все форки) см. LICENSE

🛠 Разработка

# бэкенд
python -m venv .venv && . .venv/bin/activate
pip install -e .
python -m unittest discover -s tests -v

# фронтенд (в коде — только семантические ключи t("msg_N"); перевод в рантайме)
cd frontend && pnpm install && pnpm build    # typecheck
python ../i18n/apply_i18n.py frontend       # i18n key coverage

Новая строка UI: возьмите следующий свободный msg_N, добавьте его во все словари frontend/src/lib/locales/<code>.json и вызывайте t("msg_N"). Для параметризованной строки используйте t("msg_N", { x: value }) и {x} в шаблоне.

Новый язык: положите файл frontend/src/lib/locales/<code>.json с тем же набором ключей (плюс обязательный native_name — название языка собственными словами). Он подхватится автоматически (import.meta.glob) в выпадающем меню, а верификатор начнёт требовать его полноты. en.json — язык fallback: недостающие в других языках ключи показываются на английском.

AGENTS.md — рабочие правила для AI-агентов (в т.ч. как правильно сделать re-sync с opq007/main).


📚 Лицензия

MIT (наследуется от opq007/Comfyui2api, RzMY, xundaoai — все форки MIT).