YumCut v0.1.0 配置参数详解
YumCut v0.1.0 四进程配置参数逐项详解:主应用 example.env 分组说明、存储服务 8 项、daemon 全参数表,含共享口令 403/200、CORS 白名单放行/拦截、轮询间隔与调度观测三组改配置实测。
YumCut v0.1.0 配置参数详解
目标:逐项讲清 YumCut v0.1.0 自托管四件套(主应用 app、MySQL、存储服务 storage、渲染守护 daemon)的全部关键配置参数——归属文件、含义、默认值、取值约束与修改后的生效方式,并对代表性参数做「改配置 → 看回显」的实测验证。文中参数以仓库随附的三个官方模板(
example.env、storage/env.example、daemon.env.example,快照6401fe6/c89c35f,取材日期 2026-10-25)为准,实测环境为 Docker Compose 编排的四服务部署(编排与部署全过程见《YumCut v0.1.0 Docker Compose 部署指南》)。
一、配置体系总览
YumCut 没有统一的配置文件,配置全部走环境变量,按进程拆成三组,互不通用:
| 进程 | 配置载体(部署篇实测形态) | 官方模板 | 生效方式 |
|---|---|---|---|
| 主应用 app | 编排 env_file: ./.env.app + build.args | 仓库根目录 example.env | 普通参数改后 docker compose up -d 重建即生效;NEXT_PUBLIC_* 与 NEXTAUTH_URL 编译进前端,必须重新 build |
| 存储服务 storage | 编排 environment: 直注 | 仓库根目录 env.example | 改后 docker compose up -d 生效 |
| 渲染守护 daemon | 编排 env_file: ./.env.daemon(另挂载为 /app/.daemon.env) | 仓库根目录 daemon.env.example | 改后 docker compose up -d daemon 生效 |
三条全局规则:
- 构建期与运行期分离:
NEXT_PUBLIC_STORAGE_BASE_URL、NEXTAUTH_URL在 Next.js 生产构建时被固化进前端产物,运行期改环境变量无效;其余参数都是运行期读取。 - 三处共享口令必须一致:
DAEMON_API_PASSWORD同时出现在主应用、存储服务、daemon 三处配置中,任何一处不一致,daemon 的请求会被对端以 403 拒绝(实测对照见 5.1)。 - 密钥类参数支持「内容或路径」两种写法:
UPLOAD_SIGNING_PRIVATE_KEY/UPLOAD_SIGNING_PUBLIC_KEY既可以粘贴 PEM 全文,也可以写文件路径,本文编排按路径挂载到/run/secrets/。
💡 技术拓展:「环境变量注入配置」只是十二要素应用的一种形态。常见配置方案对比——
方案 特点 适用场景 环境变量/env 文件 无侵入、与编排天然契合 容器化部署,YumCut 所用 配置文件(YAML/JSON) 结构清晰、可版本化 参数层级深的单体应用 配置中心(Apollo/Nacos) 动态下发、热更新 多实例微服务集群 YumCut 全量走环境变量,改配置即改编排再重建,没有热更新能力。
二、主应用参数详解
主应用的完整参数模板是仓库根目录的 example.env。按用途分组逐项说明,加粗项为最小可用部署的必填项。
2.1 数据库与调度
| 参数 | 含义 | 默认/示例 | 说明 |
|---|---|---|---|
DATABASE_URL | MySQL 连接串 | mysql://user:password@localhost:3306/yumcut | 库须为 utf8mb4;编排内写服务名 mysql。缺失时 Prisma 迁移与启动直接失败 |
ENABLE_PUBLISH_SCHEDULER | 定时发布总开关 | 0 | 0=对所有人关闭(白名单除外),1=全局开启 |
PUBLISH_SCHEDULER_BETA_USERS | 调度器灰度名单 | 空 | 逗号分隔的用户 ID 列表,总开关为 0 时仅这些用户可见 |
2.2 上传签名密钥对与存储地址
| 参数 | 含义 | 说明 |
|---|---|---|
UPLOAD_SIGNING_PRIVATE_KEY | RSA 私钥(PEM 内容或路径) | 主应用用它给浏览器签发上传/删除授权;生成方法见部署篇 4.2 |
UPLOAD_SIGNING_PUBLIC_KEY | RSA 公钥(PEM 内容或路径) | 主应用与存储服务各持一份用于验签 |
NEXT_PUBLIC_STORAGE_BASE_URL | 浏览器直连存储服务的地址 | 构建期固化;必须是用户浏览器可达的地址,填编排内网地址会导致上传失败(部署篇 Q4) |
TEST_STORAGE_BASE_URL | 自动化测试用的存储地址 | 仅测试场景使用 |
STORAGE_PUBLIC_URL | 存储服务对外拼接媒体链接的 base | 与存储服务侧同名参数对应 |
2.3 会话与登录
| 参数 | 含义 | 说明 |
|---|---|---|
NEXTAUTH_URL | 站点对外地址 | 生产构建强制校验,缺失直接构建失败(部署篇 Q1) |
NEXTAUTH_SECRET | 会话 JWT 签名密钥 | openssl rand -hex 32 生成;轮换后全部旧会话失效 |
ALLOW_NO_OAUTH | 逃生门:无 OAuth 时允许构建 | 自用部署设 1;此时界面无注册入口,账号开通走数据库(部署篇 5.3) |
ALLOW_NO_REVIEW_AUTH | 逃生门:跳过审核账号构建校验 | 缺 REVIEW_LOGIN_EMAIL/PASSWORD 时构建必须(部署篇 Q2) |
GOOGLE_CLIENT_ID/SECRET 等 | Google OAuth | 可选,配置后界面出现 Google 登录 |
APPLE_* 系列 | Sign in with Apple | 可选,含团队 ID、私钥、IAP 共享密钥等 |
MOBILE_JWT_SECRET 等 | 移动端会话 | 仅移动 App 接入需要 |
2.4 共享口令
| 参数 | 含义 | 说明 |
|---|---|---|
SERVICE_API_PASSWORD | 服务级接口口令 | 保护 /api/cron/planned-emails 等端点,调用方带 x-service-password 头 |
DAEMON_API_PASSWORD | daemon 专用口令 | daemon 调主应用 /api/daemon/* 与存储服务健康接口时带 x-daemon-password 头;实测 403/200 对照见 5.1 |
2.5 可选业务参数(按模板分组速查)
以下参数在最小可用部署中全部留空即可,列全以便按需启用:
- 邮件:
EMAIL_SEND_PROVIDER(postal/resend二选一)、POSTAL_API_URL/API_KEY/FROM_EMAIL/WEBHOOK_PUBLIC_KEY、RESEND_API_KEY/FROM_EMAIL/WEBHOOK_SECRET等。 - Stripe 计费:
STRIPE_SECRET_KEY、STRIPE_WEBHOOK_SECRET、STRIPE_WEEKLY_PRICE_ID($2.99/75 代币)、STRIPE_MONTHLY_PRICE_ID($19.99/750 代币)、STRIPE_MONTHLY_PRO_PRICE_ID($34.99/1500 代币)及两个 legacy 档位;自用可整组留空。 - YouTube 发布:
YOUTUBE_CLIENT_ID/SECRET、PUBLISH_CHANNEL_TOKEN_SECRET(32 位以上随机串,加密发布频道 token)。 - AI 增强:
RUNWARE_IMAGE_EDITOR_API_KEY(图生图)、VOICE_CLONE_RUNPOD_API_KEY/VOICE_CLONE_RUNPOD_ENDPOINT_ID(声音克隆,模板默认端点ine3ps1u7rkduw)。 - Telegram:
TELEGRAM_BOT_TOKEN/USERNAME/WEBHOOK_SECRET,用于账号绑定与通知。 - 界面开关:
NEXT_PUBLIC_ENABLE_AUDIO_TONE_PROMPT(0 隐藏 / 1 显示「音色提示」控件,构建期固化)。
三、存储服务参数详解
存储服务的完整模板只有 8 个参数(env.example),逐项说明:
| 参数 | 含义 | 默认/示例 | 实测要点 |
|---|---|---|---|
MEDIA_ROOT | 媒体文件落盘根目录 | ./media | 编排中固定为卷挂载点 /data/media |
STORAGE_PUBLIC_URL | 拼公开媒体链接的 base | http://localhost:4001 | 必须是外部可达地址,否则生成的链接用户打不开 |
STORAGE_ALLOWED_ORIGINS | 允许调用上传/删除接口(POST/OPTIONS)的浏览器来源 | 逗号分隔列表 | 只放行主应用来源;实测对照见 5.2 |
MEDIA_CORS_ALLOWLIST | 允许拉取 /api/media 的浏览器来源 | 同上,支持 * | 与上一项独立,媒体读取可单独放宽 |
MEDIA_REQUIRE_SIGNED_DOWNLOAD | 是否要求媒体下载 URL 带签名 | false | 默认关闭;开启后未签名下载被拒 |
UPLOAD_SIGNING_PUBLIC_KEY | 验签公钥(PEM 路径) | ./keys/upload_public.pem | 必须与主应用持有的密钥对匹配 |
DAEMON_API_PASSWORD | daemon 访问存储的共享口令 | changeme | 与主应用、daemon 三处一致 |
PORT | 监听端口 | 4001 | 本文编排固定 3333 并映射到宿主 8129 |
四、daemon 参数详解
daemon 的完整模板是 daemon.env.example,按功能分组:
4.1 身份与上游地址
| 参数 | 含义 | 说明 |
|---|---|---|
DAEMON_ID | 实例唯一标识 | 用于监控与任务锁,多实例时各取值必须不同且稳定 |
DAEMON_API_BASE_URL | 主应用地址(含协议) | 编排内网 http://app:3000 |
DAEMON_STORAGE_BASE_URL | 存储服务地址 | 编排内网 http://storage:3333 |
DAEMON_STORAGE_HEALTH_PATH | 存储健康检查路径 | 默认 /api/storage/health |
DAEMON_HEALTH_PATH | 主应用侧健康检查路径 | 默认 /api/daemon/health,启动自检用 |
DAEMON_API_PASSWORD | 共享口令 | 见全局规则 2 |
4.2 轮询与并发
| 参数 | 含义 | 默认 | 实测要点 |
|---|---|---|---|
DAEMON_INTERVAL_MS | 调度 tick 间隔(毫秒) | 1000 | 改大降低数据库轮询压力;改值实测见 5.3 |
DAEMON_MAX_CONCURRENCY | 单实例并行任务数 | 2 | tick 快照中的 capacity 字段即此值 |
DAEMON_VERBOSE_SCHEDULER | 调度器观测开关 | 关 | 设 1 后每个 tick 输出快照日志(5.3 实测) |
DAEMON_TASK_TIMEOUT_SECONDS | 单任务看门狗超时(秒) | 3600 | 超时任务被判定卡死并回收 |
DAEMON_REQUEST_TIMEOUT_MS | daemon→主应用 HTTP 超时(毫秒) | 15000 | 网络抖动大时适当调大 |
4.3 渲染工作区与脚本
| 参数 | 含义 | 说明 |
|---|---|---|
DAEMON_SCRIPT_WORKSPACE | v1 脚本工作区绝对路径 | 指向私有仓库 video-slides/ai-agent |
DAEMON_SCRIPT_WORKSPACE_V2 | v2 短视频脚本工作区 | 指向私有仓库 yumcut-shorts-tools |
DAEMON_CHARACTERS_WORKSPACE | 角色(lipsync)工作区 | 指向 yumcut-characters |
DAEMON_SCRIPT_CAPTION | 字幕渲染工作区 | 提供 render:python/render:headless 两个脚本 |
DAEMON_PROJECTS_WORKSPACE | 项目产物根目录 | 脚本、音频、日志落盘处 |
DAEMON_SCRIPT_MODE | 脚本执行模式 | fast(--fast)或 normal(旧行为) |
DAEMON_CAPTIONS_RENDERER | 字幕渲染器 | 缺省为 Python 渲染器;设 legacy 回退 Node 渲染器 |
DAEMON_AUDIO_DEFAULT_VOICE | 默认配音音色 | Kore(Gemini 音色) |
DAEMON_VOICE_CLONE_FALLBACK_DIR | 声音克隆兜底目录 | 命中时优先走 RunPod 克隆生成 |
DAEMON_SKIP_FFMPEG_CHECK | 跳过 FFmpeg 版本自检 | 逃生门;设置背景见部署篇 Q3 |
⚠️ 四个「脚本工作区」参数指向的仓库均为作者私有仓库(2026-10-25 实查 GitHub 返回 404),自托管用空目录占位即可让 daemon 正常启动与调度,但渲染任务无法真正执行——这是开源版的边界,不是配置错误。
五、配置修改与生效实测
5.1 共享口令:403/200 对照
DAEMON_API_PASSWORD 的生效验证:不带口令访问存储健康接口被拒,带正确口令放行:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://192.168.146.128:8129/api/storage/health
curl -s -H 'x-daemon-password: q1w2e3r4' http://192.168.146.128:8129/api/storage/health
实测回显:
HTTP 403
{"ok":true,"time":"2026-10-25T10:34:22.606Z"}
第一行 403 证明口令校验生效;第二行 ok:true 证明编排中存储服务侧的口令与请求携带值一致。
5.2 CORS 来源白名单:放行与拦截对照
STORAGE_ALLOWED_ORIGINS 只放行了主应用来源 http://192.168.146.128:8130。以浏览器预检(OPTIONS)验证,放行来源的响应带完整 CORS 头:
curl -s -D - -o /dev/null -X OPTIONS http://192.168.146.128:8129/api/storage/user-images \
-H 'Origin: http://192.168.146.128:8130' -H 'Access-Control-Request-Method: POST' | grep -iE '^HTTP|access-control'
实测回显:
HTTP/1.1 204 No Content
access-control-allow-credentials: true
access-control-allow-headers: content-type
access-control-allow-methods: POST,OPTIONS
access-control-allow-origin: http://192.168.146.128:8130
换成未放行来源,同样返回 204 但不带任何 CORS 头,浏览器会拦截后续真实请求:
curl -s -D - -o /dev/null -X OPTIONS http://192.168.146.128:8129/api/storage/user-images \
-H 'Origin: http://evil.example.com' -H 'Access-Control-Request-Method: POST' | grep -iE '^HTTP|access-control'
实测回显:
HTTP/1.1 204 No Content
这正是白名单的意义:服务端不报错,但浏览器因缺少 access-control-allow-origin 而拒绝把响应交给页面脚本。新增前端域名时,把该域名追加到 STORAGE_ALLOWED_ORIGINS 与 MEDIA_CORS_ALLOWLIST 两个逗号列表,docker compose up -d 后生效。
5.3 轮询间隔与调度观测:改值实测
把 .env.daemon 中 DAEMON_INTERVAL_MS 由 1000 改为 5000,并追加 DAEMON_VERBOSE_SCHEDULER=1,应用配置:
cd /opt/yumcut/stack
docker compose up -d daemon
实测回显:
Container yumcut-0-1-0-stack-daemon-1 Started
观察日志,tick 快照按 5 秒一拍输出(时间戳 10:44:10 → 15 → 20 → 25),capacity 即为 DAEMON_MAX_CONCURRENCY=2:
docker compose logs daemon --since 3m | grep -A4 'Scheduler tick snapshot' | head -12
实测回显(输出节选,实测首尾):
daemon-1 | [2026-10-25T10:44:10.113Z] INFO Scheduler tick snapshot {
daemon-1 | "capacity": 2,
daemon-1 | "eligibleCount": 0,
daemon-1 | "inFlight": 0
daemon-1 | }
daemon-1 | [2026-10-25T10:44:15.117Z] INFO Scheduler tick snapshot {
...
daemon-1 | [2026-10-25T10:44:25.120Z] INFO Scheduler tick snapshot {
eligibleCount: 0 / inFlight: 0 表示当前队列没有可领取的任务。验证完毕把两项改回原值(1000、删除观测开关)再 up -d,日志即恢复安静——观测开关只适合排障时短期开启,常规运行会持续刷日志。
六、常见问题
Q1:改了 NEXT_PUBLIC_STORAGE_BASE_URL 或 NEXTAUTH_URL 并 up -d,前端行为没有变化
原因:这两个参数在 Next.js 生产构建时固化进前端产物,运行期改环境变量无效。必须 docker compose build app && docker compose up -d 重新构建。
Q2:daemon 日志反复 403 / Invalid daemon credentials
原因:三处 DAEMON_API_PASSWORD 不一致(主应用 .env.app、存储服务编排、.env.daemon)。改齐后重建,用 5.1 的 403/200 对照验证。
Q3:构建主应用时报 NEXTAUTH_URL is required 或 /api/mobile/auth/review 收集失败
这两项是构建期强制校验,分别用构建参数 NEXTAUTH_URL 与逃生门 ALLOW_NO_REVIEW_AUTH=1 解决,完整排障实录见《YumCut v0.1.0 Docker Compose 部署指南》第八章 Q1/Q2。
Q4:上传页面报 CORS 错,但服务端日志无异常
原因:来源不在 STORAGE_ALLOWED_ORIGINS 白名单时服务端返回 204 但不下发 CORS 头,错误只出现在浏览器控制台。按 5.2 的对照法确认来源是否放行。
Q5:想让多个 daemon 实例并行渲染
为每个实例准备独立的 .env.daemon,DAEMON_ID 各不相同;数据库锁保证同一任务不被重复领取,DAEMON_MAX_CONCURRENCY 控制单实例并发。多实例共享同一个 DAEMON_PROJECTS_WORKSPACE 时需要自行保证路径不冲突。
七、参考链接
- 主应用配置模板
example.env(随源码分发,快照 6401fe6):https://github.com/IgorShadurin/app.yumcut.com - 存储服务配置模板
env.example(随源码分发,快照 c89c35f):https://github.com/IgorShadurin/yumcut-storage - daemon 配置模板
daemon.env.example(随主应用源码分发) - 部署与编排全过程:《YumCut v0.1.0 Docker Compose 部署指南》