部署侧接线阿里云抠图凭证,避免抠图兜底静默塌成两级

aliyun_matting_enabled 默认 true,但 env 模板/校验器从未提供
GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_*,标准部署里 build_matting_client 因缺 key
返回 None,BgFilter 失败直接本地去背,与三级兜底设计口径不符。
- 两份 api-server.env.example 补 matting 段(enabled/endpoint/AccessKey 占位/timeout)
- check-api-server-env.mjs 增可选告警:enabled 但缺 AccessKey 时提示兜底层被跳过
- 开发运维文档补记该层需配 AccessKey 才生效

密钥与 OSS/SMS/token 一致,只留空占位由运维填,不写进 provision/deploy 脚本。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 08:54:28 +00:00
parent cb1dd78e1d
commit f14702362f
4 changed files with 42 additions and 1 deletions
+8
View File
@@ -35,6 +35,14 @@ GENARRATIVE_WALLET_REFUND_OUTBOX_MAX_BYTES=67108864
GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS=180000
GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3
GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=300
# BgFilter 失败后的中间兜底:阿里云通用抠图(SegmentCommonImage)。AccessKey 留空则跳过该层,
# BgFilter 失败直接本地 editor_green_screen 去背;填入后恢复 BgFilter→阿里云→本地三级兜底。
# AccessKey 也可复用标准 SDK 命名 ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET。
GENARRATIVE_ALIYUN_MATTING_ENABLED=true
GENARRATIVE_ALIYUN_MATTING_ENDPOINT=imageseg.cn-shanghai.aliyuncs.com
GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID=
GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET=
GENARRATIVE_ALIYUN_MATTING_REQUEST_TIMEOUT_MS=30000
GENARRATIVE_OTEL_ENABLED=true
OTEL_SERVICE_NAME=genarrative-api
+8
View File
@@ -35,6 +35,14 @@ GENARRATIVE_WALLET_REFUND_OUTBOX_MAX_BYTES=67108864
GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS=180000
GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3
GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=300
# BgFilter 失败后的中间兜底:阿里云通用抠图(SegmentCommonImage)。AccessKey 留空则跳过该层,
# BgFilter 失败直接本地 editor_green_screen 去背;填入后恢复 BgFilter→阿里云→本地三级兜底。
# AccessKey 也可复用标准 SDK 命名 ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET。
GENARRATIVE_ALIYUN_MATTING_ENABLED=true
GENARRATIVE_ALIYUN_MATTING_ENDPOINT=imageseg.cn-shanghai.aliyuncs.com
GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID=
GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET=
GENARRATIVE_ALIYUN_MATTING_REQUEST_TIMEOUT_MS=30000
GENARRATIVE_OTEL_ENABLED=true
OTEL_SERVICE_NAME=genarrative-api
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
@@ -61,7 +61,7 @@ Windows 本地如果已在 `%LOCALAPPDATA%\Genarrative\ffmpeg\bin` 安装 FFmpeg
生产 worker 默认 `GENARRATIVE_EXTERNAL_GENERATION_WORKER_LEASE_SECONDS=600`,只覆盖 worker 心跳抖动和短暂断连窗口,不再把 lease 当成完整任务时长;默认 `GENARRATIVE_EXTERNAL_GENERATION_WORKER_JOB_TIMEOUT_SECONDS=900`,角色动画 / 视频类长任务使用 `GENARRATIVE_EXTERNAL_GENERATION_WORKER_LONG_JOB_TIMEOUT_SECONDS=1800`。worker 在单次尝试超过执行预算后会停止当前尝试、写入失败 / 重试状态并释放 worker 槽位;如果 SpacetimeDB 当时不可写,当前租约最多再保留到 lease 过期,之后任务重新变为可领取。生产部署和 provision 脚本会给 `/etc/genarrative/api-server.env``/etc/genarrative/external-generation-worker.env` 补齐这些变量;已有自定义值不覆盖,只会把历史旧默认 `3600` 迁移为 `600`
图片画布角色图、图标素材和 UI 素材提取在绿色 / 蓝色幕布去背景时优先调用 BgFilter;默认 `GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS=180000`,连续失败达到 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3` 后熔断 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=300` 秒。BgFilter 调用失败和熔断期均先走阿里云通用抠图,只有阿里云失败才走本地幕布色去背景兜底。修改这些变量后需要重启对应 `api-server` / worker 进程;排查时先从 worker 启动日志确认 lease 和 job timeout,再看 `editor_bgfilter_request_start``editor_bgfilter_fallback_to_aliyun_matting``editor_bgfilter_circuit_open_fallback_to_aliyun_matting`,以及阿里云失败后的 `editor_aliyun_matting_fallback_to_local_screen_background_removal` 日志。
图片画布角色图、图标素材和 UI 素材提取在绿色 / 蓝色幕布去背景时优先调用 BgFilter;默认 `GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS=180000`,连续失败达到 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3` 后熔断 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=300` 秒。BgFilter 调用失败和熔断期均先走阿里云通用抠图,只有阿里云失败才走本地幕布色去背景兜底。阿里云这层默认 `GENARRATIVE_ALIYUN_MATTING_ENABLED=true`,但必须在 `api-server.env` 填入 `GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID` / `GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET`(或标准 SDK 命名 `ALIBABA_CLOUD_ACCESS_KEY_ID` / `ALIBABA_CLOUD_ACCESS_KEY_SECRET`)才会真正启用;AccessKey 缺失时启动日志会打印「阿里云抠图 AccessKey 未配置,跳过抠图客户端初始化」,抠图直接塌成 BgFilter→本地两级,`npm run check:api-server-env` 也会给出对应告警。修改这些变量后需要重启对应 `api-server` / worker 进程;排查时先从 worker 启动日志确认 lease 和 job timeout,再看 `editor_bgfilter_request_start``editor_bgfilter_fallback_to_aliyun_matting``editor_bgfilter_circuit_open_fallback_to_aliyun_matting`,以及阿里云失败后的 `editor_aliyun_matting_fallback_to_local_screen_background_removal` 日志。
`我的` 页签或排障面板展示队列等待时,只读取 BFF 队列接口:`GET /api/runtime/external-generation/queue-overview` 查看当前用户可见队列概览,`GET /api/runtime/external-generation/jobs/{jobId}` 查看单 job 状态。生成页 / 进度页不承接队列概览,只展示当前玩法业务进度;队列接口只提供等待 / 运行 / 失败 / 完成状态补充,最终草稿、作品和结果页仍要轮询对应玩法 session/detail 接口收敛到 ready 或 failed;不要直接查询 `external_generation_job` private table,也不要把 worker 内部 payload 暴露到前端。
+25
View File
@@ -47,6 +47,31 @@ if (typoKeys.length > 0) {
);
}
// 阿里云通用抠图兜底层:默认 enabled=true,但 AccessKey 缺失时会被静默跳过,
// BgFilter 失败直接本地去背(质量下降)。属可选降级项,只告警不阻断部署。
console.log('[api-server-env] 抠图兜底(阿里云通用抠图)配置检查');
const mattingEnabled = env.GENARRATIVE_ALIYUN_MATTING_ENABLED !== 'false';
const mattingKeyPresent =
hasValue(env.GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID) ||
hasValue(env.ALIBABA_CLOUD_ACCESS_KEY_ID);
const mattingSecretPresent =
hasValue(env.GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET) ||
hasValue(env.ALIBABA_CLOUD_ACCESS_KEY_SECRET);
printStatus(
'GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_ID',
mattingKeyPresent,
);
printStatus(
'GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET / ALIBABA_CLOUD_ACCESS_KEY_SECRET',
mattingSecretPresent,
);
if (mattingEnabled && !(mattingKeyPresent && mattingSecretPresent)) {
console.warn(
'[api-server-env] 警告:GENARRATIVE_ALIYUN_MATTING_ENABLED 未关闭但缺少 AccessKey' +
'阿里云抠图兜底层将被跳过,BgFilter 失败后直接本地去背(质量下降)。',
);
}
if (missing.length > 0) {
console.error(`[api-server-env] 缺少:${missing.join(', ')}`);
process.exit(1);