Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a86125246e | ||
|
|
4c7681b338 | ||
|
|
e3c67fc8cf |
@@ -10,6 +10,9 @@ gateway/config.json
|
|||||||
# worker 配置(含鉴权密码,不入 git)
|
# worker 配置(含鉴权密码,不入 git)
|
||||||
worker_config.json
|
worker_config.json
|
||||||
|
|
||||||
|
# ComfyUI Basic Auth 密码(不入 git)
|
||||||
|
password.txt
|
||||||
|
|
||||||
# worker 运行期文件(PID / 日志)
|
# worker 运行期文件(PID / 日志)
|
||||||
worker.pid
|
worker.pid
|
||||||
worker.log
|
worker.log
|
||||||
|
|||||||
@@ -226,6 +226,24 @@ async def resolve_image_bytes(image_file, image_url, image_base64):
|
|||||||
return None, err(1008, "base64 解码失败")
|
return None, err(1008, "base64 解码失败")
|
||||||
|
|
||||||
|
|
||||||
|
# 接口2/3/5 返回不透明照片,用 JPG 显著减小体积(接口1 标注图含透明,仍用 PNG)
|
||||||
|
_JPG_QUALITY = int(os.getenv("JPG_QUALITY", "90"))
|
||||||
|
|
||||||
|
|
||||||
|
def _jpg_b64(bgr) -> str:
|
||||||
|
"""BGR 图 → JPG base64。"""
|
||||||
|
_ok, buf = cv2.imencode(".jpg", bgr, [cv2.IMWRITE_JPEG_QUALITY, _JPG_QUALITY])
|
||||||
|
return base64.b64encode(buf.tobytes()).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def _png_to_jpg_b64(png_bytes) -> str:
|
||||||
|
"""ComfyUI 返回的 PNG 字节 → 重编码为 JPG base64;无法解码则原样透传。"""
|
||||||
|
img = cv2.imdecode(np.frombuffer(png_bytes, np.uint8), cv2.IMREAD_COLOR)
|
||||||
|
if img is None:
|
||||||
|
return base64.b64encode(png_bytes).decode()
|
||||||
|
return _jpg_b64(img)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# 通用图片请求 Body(JSON 方式,用于 url / base64)
|
# 通用图片请求 Body(JSON 方式,用于 url / base64)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -514,12 +532,10 @@ async def hair_grow(
|
|||||||
|
|
||||||
results = []
|
results = []
|
||||||
for p in items:
|
for p in items:
|
||||||
_ok, png = cv2.imencode(".png", p["image_bgr"])
|
|
||||||
grown_b64 = (base64.b64encode(p["grown_png"]).decode()
|
|
||||||
if p["grown_png"] else None)
|
|
||||||
results.append({
|
results.append({
|
||||||
"image_base64": base64.b64encode(png.tobytes()).decode(),
|
"image_base64": _jpg_b64(p["image_bgr"]), # 预览图 JPG
|
||||||
"grown_image_base64": grown_b64,
|
"grown_image_base64": (_png_to_jpg_b64(p["grown_png"]) # 生发图 JPG
|
||||||
|
if p["grown_png"] else None),
|
||||||
"hairline_type": p["hairline_type"],
|
"hairline_type": p["hairline_type"],
|
||||||
"order": p["order"],
|
"order": p["order"],
|
||||||
})
|
})
|
||||||
@@ -602,7 +618,7 @@ async def hair_grow_b(
|
|||||||
if res["status"] == "no_line":
|
if res["status"] == "no_line":
|
||||||
return err(1001, "未检测到发际线划线,请确认划线图额头有清晰的手绘发际线")
|
return err(1001, "未检测到发际线划线,请确认划线图额头有清晰的手绘发际线")
|
||||||
|
|
||||||
grown_b64 = base64.b64encode(res["grown_png"]).decode() if res["grown_png"] else None
|
grown_b64 = _png_to_jpg_b64(res["grown_png"]) if res["grown_png"] else None # 生发图 JPG
|
||||||
data = {
|
data = {
|
||||||
"hair_growth_image_base64": grown_b64,
|
"hair_growth_image_base64": grown_b64,
|
||||||
"hairline_type": "custom",
|
"hairline_type": "custom",
|
||||||
@@ -783,9 +799,8 @@ async def hairline_generate(
|
|||||||
|
|
||||||
hairline_images = []
|
hairline_images = []
|
||||||
for it in res["images"]:
|
for it in res["images"]:
|
||||||
_ok, png = cv2.imencode(".png", it["image_bgr"])
|
|
||||||
hairline_images.append({
|
hairline_images.append({
|
||||||
"image_base64": base64.b64encode(png.tobytes()).decode(),
|
"image_base64": _jpg_b64(it["image_bgr"]), # 发际线叠图 JPG
|
||||||
"order": it["order"],
|
"order": it["order"],
|
||||||
})
|
})
|
||||||
c = res["best_center"]
|
c = res["best_center"]
|
||||||
|
|||||||
+5
-1
@@ -35,6 +35,8 @@
|
|||||||
| 4 | (网关本机产出,无图片字段,`features` 为 JSON 字符串) | — |
|
| 4 | (网关本机产出,无图片字段,`features` 为 JSON 字符串) | — |
|
||||||
|
|
||||||
> 实现建议:递归遍历 data,凡 key 以 `_base64` 结尾就落盘改 `_url`,自动覆盖嵌套/新增字段。
|
> 实现建议:递归遍历 data,凡 key 以 `_base64` 结尾就落盘改 `_url`,自动覆盖嵌套/新增字段。
|
||||||
|
> **图片格式**:接口1 标注图含透明用 **PNG**;接口2/3/5 是不透明照片用 **JPG**(小很多,~9×)。
|
||||||
|
> 网关落盘按内容嗅探扩展名(PNG 头→`.png`,否则 `.jpg`)。
|
||||||
|
|
||||||
### 错误码
|
### 错误码
|
||||||
|
|
||||||
@@ -84,7 +86,9 @@
|
|||||||
- ⚠️ 本机 **RTX 5090(sm_120)**,pinned `torch 2.2.2(cu121)` 只到 sm_90 → GPU 算子报 "no kernel image",
|
- ⚠️ 本机 **RTX 5090(sm_120)**,pinned `torch 2.2.2(cu121)` 只到 sm_90 → GPU 算子报 "no kernel image",
|
||||||
代码已自动**回退 CPU**(BiSeNet/SegFormer CPU 推理可用)。要用 5090 GPU 需换 torch cu128(≥2.7)。
|
代码已自动**回退 CPU**(BiSeNet/SegFormer CPU 推理可用)。要用 5090 GPU 需换 torch cu128(≥2.7)。
|
||||||
- 模型权重/字体见 [`../OFFLINE_ASSETS.md`](../OFFLINE_ASSETS.md);BiSeNet/SegFormer/face_landmarker.task 本地。
|
- 模型权重/字体见 [`../OFFLINE_ASSETS.md`](../OFFLINE_ASSETS.md);BiSeNet/SegFormer/face_landmarker.task 本地。
|
||||||
- 生发接口依赖本机 **ComfyUI(8182)**(Flux-2,它自带支持 5090 的 torch);worker 只调其 HTTP API,不跑 Flux。
|
- 生发接口依赖本机 **ComfyUI(8188)**(Flux-2,它自带支持 5090 的 torch);worker 只调其 HTTP API,不跑 Flux。
|
||||||
|
ComfyUI 开了 **HTTP Basic Auth**(user `admin` + 密码);密码放 `password.txt`(不入 git) /
|
||||||
|
`worker_config.json.comfyui_password` / 环境变量 `COMFYUI_PASSWORD`,URL 用 `COMFYUI_URL`。
|
||||||
- `worker_config.json`(不入 git):`accept_passwords`(鉴权) + 鉴权头 `X-Internal-Token`。
|
- `worker_config.json`(不入 git):`accept_passwords`(鉴权) + 鉴权头 `X-Internal-Token`。
|
||||||
|
|
||||||
**网关机**
|
**网关机**
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# 网关侧改动清单(worker 近期变更引发)
|
||||||
|
|
||||||
|
> 给网关开发:以下是 worker/契约近期变化里**与网关有关**的点。标 ✅ 的我已在本仓库 `gateway/`
|
||||||
|
> 改好(你 review/拉取即可);标 🔲 的是**建议你确认或改**。功能必需只有第 1 条。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. ✅【功能必需】base64→URL 落盘扩展名按内容嗅探(支持 JPG)
|
||||||
|
|
||||||
|
**背景**:接口 **2/3/5 的返回图改成了 JPG**(体积约小 9×),**接口 1 标注图仍是 PNG**(含透明)。
|
||||||
|
网关把 `*_base64` 落盘时若**硬编码 `.png`**,JPG 会被存成 `.png`(内容是 JPG、扩展名错)。
|
||||||
|
|
||||||
|
**改动**(`gateway/forward.py` 的 `rewrite_base64_to_url`,已改):
|
||||||
|
```python
|
||||||
|
# 原:filename = f"{uuid.uuid4().hex}.png"
|
||||||
|
ext = "png" if img_bytes[:8] == b"\x89PNG\r\n\x1a\n" else "jpg" # 按内容嗅探
|
||||||
|
filename = f"{uuid.uuid4().hex}.{ext}"
|
||||||
|
```
|
||||||
|
> 这样接口1 存 `.png`、接口2/3/5 存 `.jpg`,对外 URL 后缀也就正确。**若你的网关是独立部署/独立代码,按上面这两行改一下即可。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 🔲【建议】生发接口超时调大
|
||||||
|
|
||||||
|
接口 **2(一次 N 张 Flux,~18s)/ 3(~6s)** 经 ComfyUI 同步出图较慢。
|
||||||
|
`gateway/config.json` 的 `dispatch.request_timeout_seconds` 建议 **≥ 120**,否则网关会先超时换 worker 重试。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 🔲【确认】base64→URL 通用改写仍覆盖这些场景
|
||||||
|
|
||||||
|
- **数组里的图片字段**:接口2 `results[].image_base64` / `results[].grown_image_base64`、
|
||||||
|
接口5 `hairline_images[].image_base64` 在数组元素内——改写要**递归进数组**(你现有的递归实现已覆盖)。
|
||||||
|
- **可空字段**:接口2/3 的生发图(ComfyUI 没起/失败时)`*_base64` 为 **null** → 保留 null、不落盘。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 🔲【可选·仅影响 /docs】OpenAPI 表单声明
|
||||||
|
|
||||||
|
纯文档展示,不影响转发功能(网关是盲转发)。若想让网关 `/docs` 准确:
|
||||||
|
- 接口2 `/hair/grow`、接口5 `/hairline/generate` 入参**新增必填 `gender`**(male/female)。
|
||||||
|
- 接口3 `/hair/grow-b` 入参**只剩 `marked_image_*`**(已去掉 `original_image_*`)。
|
||||||
|
- (`gateway/app.py` 里的 `_*_FORMS` 字典当前未被路由引用,所以不改也不影响实际行为。)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已经做好、无需再动的
|
||||||
|
|
||||||
|
- **接口4 在网关本机实现**(调豆包,不转发 worker)——已完成;config 里配 `ark`。
|
||||||
|
- **接口4 业务错误 HTTP 状态**已统一为 200(与其余接口一致)。
|
||||||
|
- **接口3 去 original / best_hairline**——网关盲转发,无需改(映射表里也没有 best_hairline)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> 对外字段映射总表见 [`实现说明.md`](实现说明.md) §1;契约以 [`接口文档.md`](接口文档.md) 为准。
|
||||||
+3
-2
@@ -102,8 +102,9 @@ def rewrite_base64_to_url(
|
|||||||
if key.endswith("_base64") and isinstance(value, str):
|
if key.endswith("_base64") and isinstance(value, str):
|
||||||
img_bytes = _decode_base64_value(value)
|
img_bytes = _decode_base64_value(value)
|
||||||
if img_bytes is not None:
|
if img_bytes is not None:
|
||||||
# 生成文件名并落盘
|
# 按内容嗅探扩展名:PNG(接口1标注图,含透明) / JPEG(接口2/3/5 照片)
|
||||||
filename = f"{uuid.uuid4().hex}.png"
|
ext = "png" if img_bytes[:8] == b"\x89PNG\r\n\x1a\n" else "jpg"
|
||||||
|
filename = f"{uuid.uuid4().hex}.{ext}"
|
||||||
filepath = Path(static_dir) / filename
|
filepath = Path(static_dir) / filename
|
||||||
filepath.write_bytes(img_bytes)
|
filepath.write_bytes(img_bytes)
|
||||||
|
|
||||||
|
|||||||
+31
-4
@@ -1,7 +1,8 @@
|
|||||||
"""ComfyUI 客户端:用 add_hair.json 工作流跑生发图(Flux-2 inpaint)。
|
"""ComfyUI 客户端:用 add_hair.json 工作流跑生发图(Flux-2 inpaint)。
|
||||||
|
|
||||||
worker 不跑 Flux,只把「划线图 + 遮罩」的 RGBA 上传到本机 ComfyUI(默认 8182),
|
worker 不跑 Flux,只把「划线图 + 遮罩」的 RGBA 上传到本机 ComfyUI(默认 8188),
|
||||||
替换工作流节点 26 的输入图、随机 seed,提交 /prompt,轮询 /history,取回 /view 输出。
|
替换工作流节点 26 的输入图、随机 seed,提交 /prompt,轮询 /history,取回 /view 输出。
|
||||||
|
ComfyUI 开启了 HTTP Basic Auth(user `admin` + 密码),所有请求都带凭据。
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -14,12 +15,13 @@ import uuid
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
COMFYUI_URL = os.getenv("COMFYUI_URL", "http://127.0.0.1:8182").rstrip("/")
|
COMFYUI_URL = os.getenv("COMFYUI_URL", "http://127.0.0.1:8188").rstrip("/")
|
||||||
WORKFLOW_PATH = os.getenv(
|
WORKFLOW_PATH = os.getenv(
|
||||||
"ADD_HAIR_WORKFLOW",
|
"ADD_HAIR_WORKFLOW",
|
||||||
os.path.join(os.path.dirname(os.path.dirname(__file__)), "add_hair.json"),
|
os.path.join(os.path.dirname(os.path.dirname(__file__)), "add_hair.json"),
|
||||||
)
|
)
|
||||||
COMFY_TIMEOUT = float(os.getenv("COMFYUI_TIMEOUT", "600")) # 单张出图最长等待(秒)
|
COMFY_TIMEOUT = float(os.getenv("COMFYUI_TIMEOUT", "600")) # 单张出图最长等待(秒)
|
||||||
|
_REPO = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
_INPUT_NODE = "26" # LoadImage:外部输入图(含 alpha 遮罩)
|
_INPUT_NODE = "26" # LoadImage:外部输入图(含 alpha 遮罩)
|
||||||
_SEED_NODE = "6" # RandomNoise
|
_SEED_NODE = "6" # RandomNoise
|
||||||
@@ -28,6 +30,31 @@ _OUTPUT_NODE = "17" # SaveImage
|
|||||||
_workflow = None
|
_workflow = None
|
||||||
|
|
||||||
|
|
||||||
|
def _comfy_auth():
|
||||||
|
"""ComfyUI Basic Auth 凭据 (user, password)。
|
||||||
|
|
||||||
|
user:环境变量 COMFYUI_USER,默认 admin。
|
||||||
|
password:环境变量 COMFYUI_PASSWORD → worker_config.json.comfyui_password → password.txt。
|
||||||
|
无密码则返回 None(不带鉴权,兼容未开启 auth 的实例)。
|
||||||
|
"""
|
||||||
|
user = os.getenv("COMFYUI_USER", "admin")
|
||||||
|
pw = os.getenv("COMFYUI_PASSWORD")
|
||||||
|
if not pw:
|
||||||
|
cfg = os.path.join(_REPO, "worker_config.json")
|
||||||
|
if os.path.isfile(cfg):
|
||||||
|
try:
|
||||||
|
with open(cfg, encoding="utf-8") as f:
|
||||||
|
pw = json.load(f).get("comfyui_password")
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
pw = None
|
||||||
|
if not pw:
|
||||||
|
pwfile = os.path.join(_REPO, "password.txt")
|
||||||
|
if os.path.isfile(pwfile):
|
||||||
|
with open(pwfile, encoding="utf-8") as f:
|
||||||
|
pw = f.read().strip()
|
||||||
|
return (user, pw) if pw else None
|
||||||
|
|
||||||
|
|
||||||
def _load_workflow() -> dict:
|
def _load_workflow() -> dict:
|
||||||
global _workflow
|
global _workflow
|
||||||
if _workflow is None:
|
if _workflow is None:
|
||||||
@@ -39,7 +66,7 @@ def _load_workflow() -> dict:
|
|||||||
def run(rgba_png_bytes: bytes, timeout: float = COMFY_TIMEOUT) -> bytes:
|
def run(rgba_png_bytes: bytes, timeout: float = COMFY_TIMEOUT) -> bytes:
|
||||||
"""提交一次生发任务,返回输出 PNG 字节。失败抛异常。"""
|
"""提交一次生发任务,返回输出 PNG 字节。失败抛异常。"""
|
||||||
client_id = uuid.uuid4().hex
|
client_id = uuid.uuid4().hex
|
||||||
with httpx.Client(base_url=COMFYUI_URL, timeout=30.0) as cli:
|
with httpx.Client(base_url=COMFYUI_URL, timeout=30.0, auth=_comfy_auth()) as cli:
|
||||||
# 1. 上传输入图(含 alpha 遮罩)到 ComfyUI input 目录
|
# 1. 上传输入图(含 alpha 遮罩)到 ComfyUI input 目录
|
||||||
fname = f"hair_{client_id}.png"
|
fname = f"hair_{client_id}.png"
|
||||||
r = cli.post("/upload/image", files={"image": (fname, rgba_png_bytes, "image/png")},
|
r = cli.post("/upload/image", files={"image": (fname, rgba_png_bytes, "image/png")},
|
||||||
@@ -92,7 +119,7 @@ def run(rgba_png_bytes: bytes, timeout: float = COMFY_TIMEOUT) -> bytes:
|
|||||||
def ping() -> bool:
|
def ping() -> bool:
|
||||||
"""探测 ComfyUI 是否在线(/system_stats)。"""
|
"""探测 ComfyUI 是否在线(/system_stats)。"""
|
||||||
try:
|
try:
|
||||||
with httpx.Client(base_url=COMFYUI_URL, timeout=3.0) as cli:
|
with httpx.Client(base_url=COMFYUI_URL, timeout=3.0, auth=_comfy_auth()) as cli:
|
||||||
return cli.get("/system_stats").status_code == 200
|
return cli.get("/system_stats").status_code == 200
|
||||||
except Exception: # noqa: BLE001
|
except Exception: # noqa: BLE001
|
||||||
return False
|
return False
|
||||||
|
|||||||
+8
-7
@@ -82,9 +82,10 @@ def test_grow_missing_gender_1004(client):
|
|||||||
assert r.json()["code"] == 1004
|
assert r.json()["code"] == 1004
|
||||||
|
|
||||||
|
|
||||||
_PNG_1x1 = base64.b64decode(
|
# mock ComfyUI 输出:一张合法 PNG(worker 会把它重编码成 JPG)
|
||||||
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
|
import cv2 as _cv2
|
||||||
)
|
import numpy as _np
|
||||||
|
_PNG_1x1 = _cv2.imencode(".png", _np.full((8, 8, 3), 200, _np.uint8))[1].tobytes()
|
||||||
|
|
||||||
|
|
||||||
def test_grow_female_returns_5(client, monkeypatch):
|
def test_grow_female_returns_5(client, monkeypatch):
|
||||||
@@ -99,8 +100,8 @@ def test_grow_female_returns_5(client, monkeypatch):
|
|||||||
results = body["data"]["results"]
|
results = body["data"]["results"]
|
||||||
assert [x["hairline_type"] for x in results] == ["ellipse", "flower", "heart", "straight", "wave"]
|
assert [x["hairline_type"] for x in results] == ["ellipse", "flower", "heart", "straight", "wave"]
|
||||||
assert [x["order"] for x in results] == [1, 2, 3, 4, 5]
|
assert [x["order"] for x in results] == [1, 2, 3, 4, 5]
|
||||||
assert base64.b64decode(results[0]["image_base64"])[:8] == b"\x89PNG\r\n\x1a\n"
|
assert base64.b64decode(results[0]["image_base64"])[:3] == b"\xff\xd8\xff" # JPEG
|
||||||
assert base64.b64decode(results[0]["grown_image_base64"])[:8] == b"\x89PNG\r\n\x1a\n"
|
assert base64.b64decode(results[0]["grown_image_base64"])[:3] == b"\xff\xd8\xff" # JPEG
|
||||||
assert "image_url" not in results[0]
|
assert "image_url" not in results[0]
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ def test_growb_success(client, monkeypatch):
|
|||||||
assert body["code"] == 0, body
|
assert body["code"] == 0, body
|
||||||
d = body["data"]
|
d = body["data"]
|
||||||
assert d["hairline_type"] == "custom"
|
assert d["hairline_type"] == "custom"
|
||||||
assert base64.b64decode(d["hair_growth_image_base64"])[:8] == b"\x89PNG\r\n\x1a\n"
|
assert base64.b64decode(d["hair_growth_image_base64"])[:3] == b"\xff\xd8\xff" # JPEG
|
||||||
assert "best_hairline_image_base64" not in d # 已去掉该字段
|
assert "best_hairline_image_base64" not in d # 已去掉该字段
|
||||||
assert "best_hairline_image_url" not in d
|
assert "best_hairline_image_url" not in d
|
||||||
|
|
||||||
@@ -145,7 +146,7 @@ def test_hairline_gen_female(client):
|
|||||||
assert body["code"] == 0, body
|
assert body["code"] == 0, body
|
||||||
d = body["data"]
|
d = body["data"]
|
||||||
assert [x["order"] for x in d["hairline_images"]] == [1, 2, 3, 4, 5]
|
assert [x["order"] for x in d["hairline_images"]] == [1, 2, 3, 4, 5]
|
||||||
assert base64.b64decode(d["hairline_images"][0]["image_base64"])[:8] == b"\x89PNG\r\n\x1a\n"
|
assert base64.b64decode(d["hairline_images"][0]["image_base64"])[:3] == b"\xff\xd8\xff" # JPEG
|
||||||
c = d["best_hairline_center_point"]
|
c = d["best_hairline_center_point"]
|
||||||
assert 0 <= c["x"] <= 682 and 0 <= c["y"] <= 811 # 落在原图范围内
|
assert 0 <= c["x"] <= 682 and 0 <= c["y"] <= 811 # 落在原图范围内
|
||||||
assert "image_url" not in d["hairline_images"][0]
|
assert "image_url" not in d["hairline_images"][0]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"_comment": "复制为 worker_config.json(不入 git)。accept_passwords:worker 内网鉴权密码列表,网关带 X-Internal-Token: <其中之一>(也可用环境变量 WORKER_ACCEPT_PASSWORDS 覆盖)。ark_api_key:接口4 火山方舟豆包视觉模型的 API Key(也可用环境变量 ARK_API_KEY 覆盖)。",
|
"_comment": "复制为 worker_config.json(不入 git)。accept_passwords:worker 内网鉴权密码列表,网关带 X-Internal-Token: <其中之一>(也可用环境变量 WORKER_ACCEPT_PASSWORDS 覆盖)。comfyui_password:本机 ComfyUI(8188) Basic Auth 密码(user 默认 admin;也可放 password.txt 或环境变量 COMFYUI_PASSWORD)。注:接口4 火山方舟 ark_api_key 已迁到网关配置。",
|
||||||
"accept_passwords": ["change-me-to-a-strong-secret"],
|
"accept_passwords": ["change-me-to-a-strong-secret"],
|
||||||
"ark_api_key": "your-volcengine-ark-api-key"
|
"comfyui_password": "your-comfyui-basic-auth-password"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user