fix(ops): expose release version and limit worker concurrency

This commit is contained in:
Xiaoxia AI
2026-06-23 07:52:19 +08:00
parent bf1b679f42
commit 816d98175a
6 changed files with 513 additions and 1 deletions
+266
View File
@@ -0,0 +1,266 @@
# 小虾 SaaS 功能升级优化路线图
> 状态:生效中
> 基线版本:v0.1.14
> 制定时间:2026-06-23
> 负责人:小虾 🦐
---
## 1. 背景
旧版桌面剪辑软件已经形成了一套以“剪辑工作台”为核心的本地自动剪辑经验:素材库、智能分类、素材缺口诊断、标题库、批量生成、成片历史、错误诊断与自动修复。
SaaS 版目前已经打通 MVP 主链路:登录、工作空间、项目、素材上传、异步处理、真实 FFmpeg 生成、成片下载、生产发布与基础权限边界。下一阶段的重点不是继续临时堆功能,而是把旧版软件中真正有价值的剪辑经验,按标准化、模块化方式迁移到 SaaS。
---
## 2. 总目标
把小虾 SaaS 从“能上传素材并生成 MP4 的 MVP”升级为“具备素材诊断、标题资产、成片管理、任务追踪、模板编排和智能增强能力的自动剪辑平台”。
核心原则:
1. 文档先行,开发前明确需求、接口、页面、测试、验收、发布。
2. 模块隔离,素材、标题、生成、成片、任务、权限分别设计和验收。
3. 不做假入口,未实现能力必须显示“暂未开放”或禁用。
4. 长任务必须异步,必须有状态、进度、失败原因和重试策略。
5. 每次上线必须通过本地测试、CI、生产 smoke 和真实用户主链路验收。
6. 生产机不得承担构建任务,生产发布必须使用预构建产物和镜像。
---
## 3. 当前基线
### 3.1 已验证生产能力
- 账号注册、登录、登录态清理。
- 工作空间与项目管理。
- 项目级素材库。
- 单文件与批量上传。
- 上传后异步 ingest job。
- 真实 FFmpeg 生成 MP4。
- 成片下载。
- 基础权限边界:匿名、非成员访问项目/素材/上传会被拦截。
- 生产发布链路:runtime-builder 构建,生产机加载镜像和产物。
- 未开放功能显式“暂未开放”。
### 3.2 旧版核心能力差距
- 缺少素材智能视图:推荐、慎用、高风险、未使用、最近使用、待复核。
- 缺少素材准备度和缺口诊断。
- 缺少完整标题库:分类、常用、使用次数、自动选标题。
- 缺少成熟成片历史、封面预览、复核流和批量下载。
- 缺少统一任务中心:上传、分类、生成、下载任务状态与日志。
- 缺少速度/均衡/质量优先、多候选生成和筛选策略。
- 缺少模板驱动的剪辑计划预览。
- 缺少 ASR 字幕、TTS 配音、BGM 混音、转场包装和脚本到剪辑计划。
---
## 4. 阶段路线
### 阶段 0:生产稳定与现状冻结
目标:确认当前 SaaS MVP 稳定可用,避免后续升级带着旧问题滚雪球。
步骤:
1. 固定当前生产基线版本和能力清单。
2. 真实浏览器跑通:登录 → 工作空间 → 项目 → 批量上传 → 生成 → 下载。
3. 收集所有截图、错误文案、卡顿、失败提示。
4. 按账号、项目、素材、任务四个维度定位根因。
5. 更新当前发布表面文档,明确可用和不可用功能。
验收标准:主链路真实用户可完成一次完整生成并下载 MP4。
---
### 阶段 1:旧版功能拆解成 SaaS 模块
目标:把旧版桌面软件能力拆成 SaaS 可开发模块,禁止散落开发。
模块划分:
1. 素材中心:视频素材库、配音素材库、批量上传、素材分类、智能视图、缺口诊断。
2. 标题中心:标题库、标题分类、常用标题、使用次数、自动选标题。
3. 剪辑生成中心:生成模式、生成数量、生成质量、多候选生成、进度、停止、重试。
4. 成片中心:成片列表、封面预览、下载、批量下载、复核状态、生成参数回放。
5. 任务中心:上传任务、分类任务、生成任务、失败原因、日志追踪、可重试。
6. 权限与审计:工作空间成员权限、素材权限、成片权限、任务权限、操作记录。
验收标准:每个旧版功能都有明确 SaaS 模块归属、数据对象、页面入口和验收标准。
---
### 阶段 2:素材中心升级
目标:优先迁移旧版“素材智能诊断”,这是区别普通剪辑工具的核心能力。
步骤:
1. 设计素材扩展字段:素材类型、分类、风险分、质量分、使用次数、最近使用时间、复核状态。
2. 明确分类结果属于 project、asset_library、asset 三层中的哪一层。
3. Worker 上传后自动分类:口播、场景、待复核。
4. 增加智能视图接口:全部、口播、场景、待复核、推荐、慎用、高风险、未使用、最近使用。
5. 前端素材页增加筛选标签、统计摘要和复核状态。
6. 增加素材缺口诊断接口,输出准备度分数、问题、建议。
7. 前端增加“素材诊断”面板。
验收标准:用户上传一批素材后,系统能告诉用户“够不够剪、缺什么、哪些素材慎用、哪些素材推荐使用”。
---
### 阶段 3:标题库升级
目标:把旧版标题库迁移成团队和项目可复用的内容资产。
步骤:
1. 设计标题表:workspace_id、project_id、title、category、favorite、use_count。
2. 后端实现标题增删改查。
3. 实现标题搜索、分类筛选、常用标题。
4. 实现“自动选一个”逻辑:优先常用、低使用次数、匹配项目分类。
5. 生成页接入标题库选择。
6. 生成成功后更新标题使用次数。
验收标准:用户可以维护标题资产,生成时可手选或自动选择标题,不需要每次手填。
---
### 阶段 4:成片中心升级
目标:让生成结果可管理,而不是只生成一个下载链接。
步骤:
1. 设计成片状态:生成中、成功、失败、待复核、可发布。
2. 保存生成参数:素材库、标题、模式、数量、模板、时间。
3. 生成结果增加封面图或首帧预览。
4. 前端成片页展示列表、预览、下载、失败原因。
5. 增加批量下载。
6. 增加“标记为可发布/需复核”。
验收标准:用户能回看历史成片,知道每条视频怎么生成、能不能发布,并可批量处理结果。
---
### 阶段 5:任务中心与错误追踪
目标:所有长任务都可追踪、可解释、可重试。
步骤:
1. 统一任务模型:upload、classify、generate、download/export。
2. 统一状态:queued、running、completed、failed、cancelled。
3. 每个任务保存进度、当前步骤、失败类型、原始错误、用户提示。
4. 前端增加任务中心入口。
5. 失败任务支持重试。
6. 所有用户可见错误都必须映射成人话提示。
验收标准:任何失败都能回答四句话:哪一步失败、为什么失败、能不能重试、用户该怎么办。
---
### 阶段 6Phase 8 模板与编排引擎
目标:从“黑盒生成视频”升级为“模板驱动的剪辑计划”。
步骤:
1. 设计模板模型:模板名称、场景结构、素材要求、时长规则、标题规则。
2. 设计 EditPlan:一次生成前先形成剪辑计划。
3. 设计 EditPlanClip:每个片段对应素材、开始时间、持续时间、转场、音频。
4. 自动选片:根据素材分类、风险、质量、使用次数选择素材。
5. 前端增加剪辑计划预览。
6. 用户确认后再执行 FFmpeg 生成。
7. 生成结果绑定模板和剪辑计划。
验收标准:用户能看到“系统准备怎么剪”,确认后再生成,而不是黑盒随机生成。
---
### 阶段 7Phase 9 智能增强
目标:补齐真正智能剪辑能力。
步骤:
1. ASR 字幕:识别配音或视频语音,生成字幕。
2. TTS 配音:文本生成配音,未配置服务时 UI 不开放。
3. BGM 混音:背景音乐、音量 ducking、淡入淡出。
4. 转场包装:片段间转场、片头片尾、水印。
5. 脚本到剪辑计划:输入脚本,生成素材需求和剪辑结构。
6. 智能推荐:根据素材库情况推荐模板和生成策略。
验收标准:小虾从“视频生成工具”升级成“智能剪辑助理”。
---
### 阶段 8:权限、安全与商业化准备
目标:为正式商业 SaaS 做底座。
步骤:
1. 扫权限边界:素材列表、成片下载、生成任务、标题库、任务日志。
2. 工作空间成员权限细化:owner、admin、member、viewer。
3. 操作审计:上传、删除、生成、下载、邀请成员。
4. 配额体系:素材容量、生成次数、并发任务、存储周期。
5. 订阅和账单继续保持“暂未开放”,等后端完整后再启用。
验收标准:多人使用不会越权,资源可计量,后续可接商业化。
---
## 5. 开发包顺序
1. 生产 UAT 问题清零与当前能力冻结。
2. 素材智能视图与素材缺口诊断。
3. 标题库。
4. 成片中心。
5. 任务中心。
6. 模板与剪辑计划。
7. ASR、TTS、BGM、转场智能增强。
8. 权限、审计、配额、商业化底座。
---
## 6. 每个开发包必须交付的内容
每个开发包必须包含:
1. 需求说明。
2. 数据模型设计。
3. API 设计。
4. 前端页面设计。
5. Worker/异步任务设计,如适用。
6. 权限边界说明。
7. 错误提示与失败处理说明。
8. 单元测试和集成测试。
9. 前端 type-check 和 build。
10. 生产 smoke 或手工验收记录。
11. 发布说明和回滚点。
---
## 7. 禁止事项
1. 禁止未设计数据模型就直接写页面。
2. 禁止后端未实现时前端假成功。
3. 禁止把长任务做成同步阻塞接口。
4. 禁止跳过 workspace/project/member 权限校验。
5. 禁止生产机承担 Web/API/Worker 构建。
6. 禁止未经 smoke 就说生产完成。
7. 禁止把旧版功能散落迁移,必须归入模块和开发包。
---
## 8. 最近下一步
立即执行:
1. 完成生产 UAT:登录 → 工作空间 → 项目 → 批量上传 → 生成 → 下载。
2. 记录所有真实问题。
3. 补充 `docs/SAAS-UPGRADE-EXECUTION-CHECKLIST.md`
4. 开始第一个正式开发包:生产 UAT 问题清零与当前能力冻结。
+229
View File
@@ -0,0 +1,229 @@
# 小虾 SaaS 升级执行检查清单
> 对应路线图:`docs/SAAS-FUNCTION-UPGRADE-ROADMAP.md`
> 状态:生效中
> 制定时间:2026-06-23
---
## 1. 通用开工检查
每个开发包开工前必须完成:
- [ ] 已读取核心规则文档和当前路线图。
- [ ] 已确认当前工作属于哪个阶段、哪个模块。
- [ ] 已确认不会偏离 Clean Architecture。
- [ ] 已确认是否涉及数据库迁移。
- [ ] 已确认是否涉及生产发布。
- [ ] 已确认是否涉及权限边界。
- [ ] 已确认未实现功能不会在 UI 中假装可用。
---
## 2. 每个开发包的标准交付物
### 2.1 需求
- [ ] 写清楚用户是谁。
- [ ] 写清楚用户要完成什么任务。
- [ ] 写清楚当前痛点。
- [ ] 写清楚本开发包不做什么。
- [ ] 写清楚验收标准。
### 2.2 架构
- [ ] 明确 Domain 对象。
- [ ] 明确 Application Use Case。
- [ ] 明确 Ports 接口。
- [ ] 明确 Adapters 实现。
- [ ] 明确 API 路由。
- [ ] 明确 Worker 任务,如适用。
### 2.3 数据
- [ ] 明确新增表或字段。
- [ ] 明确字段归属 workspace/project/library/asset/task/result。
- [ ] 明确索引。
- [ ] 明确迁移脚本。
- [ ] 明确回滚或兼容策略。
### 2.4 API
- [ ] 明确请求方法和路径。
- [ ] 明确请求参数。
- [ ] 明确响应结构。
- [ ] 明确错误码。
- [ ] 明确鉴权要求。
- [ ] 明确 workspace/project/member 权限校验。
### 2.5 前端
- [ ] 明确页面入口。
- [ ] 明确主要状态。
- [ ] 明确加载中、空状态、失败状态。
- [ ] 明确按钮可用/禁用条件。
- [ ] 明确错误文案必须说人话。
- [ ] 明确直接 URL/刷新后的上下文恢复方式。
### 2.6 测试
- [ ] 单元测试覆盖核心 Use Case。
- [ ] 集成测试覆盖 API 正常路径。
- [ ] 集成测试覆盖权限边界。
- [ ] 前端 type-check 通过。
- [ ] 前端 build 通过。
- [ ] 生产 smoke 覆盖用户主链路。
### 2.7 发布
- [ ] develop 分支干净。
- [ ] CI 通过。
- [ ] tag 发布触发。
- [ ] runtime-builder 构建成功。
- [ ] 生产 API/Worker/Web 健康。
- [ ] 公开域名 smoke 通过。
- [ ] 记录版本号和回滚点。
---
## 3. 开发包 1:生产 UAT 问题清零与能力冻结
- [ ] 浏览器登录。
- [ ] 创建或进入工作空间。
- [ ] 创建或进入项目。
- [ ] 创建素材库。
- [ ] 批量上传素材。
- [ ] 查看上传结果。
- [ ] 发起生成任务。
- [ ] 查看生成进度。
- [ ] 下载成片。
- [ ] 截图记录所有异常。
- [ ] 查询对应 API 响应。
- [ ] 查询对应 Worker/API 日志。
- [ ] 更新当前发布表面文档。
验收:真实用户可以完整完成一次生成并下载。
---
## 4. 开发包 2:素材智能视图与缺口诊断
- [ ] 设计素材分类字段。
- [ ] 设计风险分和质量分字段。
- [ ] 设计使用次数和最近使用字段。
- [ ] 设计复核状态字段。
- [ ] 增加分类 Worker 流程。
- [ ] 增加智能视图 API。
- [ ] 增加素材诊断 API。
- [ ] 前端素材页增加筛选标签。
- [ ] 前端素材页增加统计摘要。
- [ ] 前端增加素材诊断面板。
- [ ] 测试分类、筛选、诊断、权限边界。
验收:系统能回答“素材够不够、缺什么、哪些推荐、哪些慎用”。
---
## 5. 开发包 3:标题库
- [ ] 设计标题数据模型。
- [ ] 增加标题迁移脚本。
- [ ] 增加标题 CRUD API。
- [ ] 增加搜索和分类筛选。
- [ ] 增加常用标题。
- [ ] 增加自动选标题。
- [ ] 生成页接入标题库。
- [ ] 生成成功后更新使用次数。
- [ ] 测试标题权限边界。
验收:用户可以维护标题资产,生成时可手选或自动选择。
---
## 6. 开发包 4:成片中心
- [ ] 设计成片状态。
- [ ] 保存生成参数。
- [ ] 生成封面或首帧预览。
- [ ] 成片页展示列表。
- [ ] 成片页支持预览。
- [ ] 成片页支持下载和批量下载。
- [ ] 成片页显示失败原因。
- [ ] 支持标记可发布或需复核。
- [ ] 测试成片权限边界。
验收:用户能管理历史成片并判断是否可发布。
---
## 7. 开发包 5:任务中心
- [ ] 统一任务模型。
- [ ] 统一任务状态。
- [ ] 保存进度和当前步骤。
- [ ] 保存失败类型和原始错误。
- [ ] 保存用户可读错误提示。
- [ ] 前端增加任务中心。
- [ ] 失败任务支持重试。
- [ ] 测试任务权限边界。
验收:任何失败都能解释并可按规则重试。
---
## 8. 开发包 6:模板与剪辑计划
- [ ] 设计模板模型。
- [ ] 设计 EditPlan。
- [ ] 设计 EditPlanClip。
- [ ] 实现自动选片。
- [ ] 前端增加剪辑计划预览。
- [ ] 用户确认后执行生成。
- [ ] 生成结果绑定模板和计划。
- [ ] 测试模板权限边界。
验收:用户能看到系统准备怎么剪,再确认生成。
---
## 9. 开发包 7:智能增强
- [ ] ASR 字幕能力设计。
- [ ] TTS 配音能力设计。
- [ ] BGM 混音能力设计。
- [ ] 转场包装能力设计。
- [ ] 脚本到剪辑计划能力设计。
- [ ] 未配置外部能力时 UI 禁用或显示暂未开放。
- [ ] 测试外部服务缺失时的降级行为。
验收:智能能力真实可用,不配置时不假装可用。
---
## 10. 开发包 8:权限、安全与商业化底座
- [ ] 扫素材列表权限。
- [ ] 扫成片下载权限。
- [ ] 扫生成任务权限。
- [ ] 扫标题库权限。
- [ ] 扫任务日志权限。
- [ ] 细化 workspace 成员角色。
- [ ] 增加操作审计。
- [ ] 设计配额体系。
- [ ] 订阅和账单继续保持暂未开放,直到后端完整。
验收:多人使用不越权,资源可计量。
---
## 11. 收口规则
每个开发包结束前必须回答:
1. 用户能完成什么新能力?
2. 哪些入口仍然暂未开放?
3. 哪些 API 加了权限边界?
4. 哪些失败提示已经变成人话?
5. 哪些测试和 smoke 已通过?
6. 当前生产版本是多少?
7. 回滚目标是什么?
+3
View File
@@ -10,6 +10,7 @@ services:
- ../../.env
environment:
APP_ENV: ${APP_ENV:-staging}
APP_VERSION: ${APP_VERSION:-0.1.0}
GENERATED_FILES_DIR: /app/generated
GENERATED_FILES_URL_PREFIX: /generated-files
PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com}
@@ -37,6 +38,8 @@ services:
- ../../.env
environment:
APP_ENV: ${APP_ENV:-staging}
APP_VERSION: ${APP_VERSION:-0.1.0}
WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-1}
GENERATED_FILES_DIR: /app/generated
GENERATED_FILES_URL_PREFIX: /generated-files
PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com}
+3
View File
@@ -55,6 +55,7 @@ if [ -n "$RELEASE_VERSION" ]; then
docker load -i "$RUNTIME_IMAGE_TAR"
export API_IMAGE="xiaoxia-saas-api:$RELEASE_VERSION"
export WORKER_IMAGE="xiaoxia-saas-worker:$RELEASE_VERSION"
export APP_VERSION="$RELEASE_VERSION"
fi
export DOCKER_BUILDKIT=0
@@ -62,6 +63,8 @@ export COMPOSE_DOCKER_CLI_BUILD=0
export COMPOSE_PROJECT_NAME=xiaoxia-production-app
export WEB_DOCKERFILE=infra/docker/web-artifact.Dockerfile
export WEB_NGINX_CONF=infra/docker/nginx-production.conf
export WORKER_CONCURRENCY="${WORKER_CONCURRENCY:-1}"
export WORKER_MAX_TASKS_PER_CHILD="${WORKER_MAX_TASKS_PER_CHILD:-100}"
if [ "${ALLOW_PRODUCTION_BUILDS:-false}" = "true" ]; then
docker compose --env-file "$ENV_FILE" build --pull=false api
+1 -1
View File
@@ -17,4 +17,4 @@ COPY scripts /app/scripts
COPY alembic /app/alembic
COPY alembic.ini /app/alembic.ini
WORKDIR /app/apps/worker
CMD ["celery", "-A", "worker_app.celery_app.celery_app", "worker", "--loglevel=info"]
CMD ["sh", "-c", "celery -A worker_app.celery_app.celery_app worker --loglevel=info --concurrency=${WORKER_CONCURRENCY:-1} --max-tasks-per-child=${WORKER_MAX_TASKS_PER_CHILD:-100}"]
+11
View File
@@ -33,6 +33,9 @@ def test_deploy_production_uses_production_infra_and_project():
assert "RELEASE_VERSION" in script
assert "RUNTIME_IMAGE_TAR" in script
assert "docker load -i \"$RUNTIME_IMAGE_TAR\"" in script
assert 'export APP_VERSION="$RELEASE_VERSION"' in script
assert 'export WORKER_CONCURRENCY="${WORKER_CONCURRENCY:-1}"' in script
assert 'export WORKER_MAX_TASKS_PER_CHILD="${WORKER_MAX_TASKS_PER_CHILD:-100}"' in script
assert "docker image inspect \"${API_IMAGE:-xiaoxia-saas-api:dev}\"" in script
assert "docker image inspect \"${WORKER_IMAGE:-xiaoxia-saas-worker:dev}\"" in script
assert "ALLOW_PRODUCTION_BUILDS=true" in script
@@ -111,8 +114,16 @@ def test_deploy_scripts_build_web_image_explicitly():
assert "docker compose --env-file \"$ENV_FILE\" build --pull=false web" in production_script
assert "dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile}" in compose
assert "NGINX_CONF: ${WEB_NGINX_CONF:-infra/docker/nginx.conf}" in compose
assert "APP_VERSION: ${APP_VERSION:-0.1.0}" in compose
assert "WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-1}" in compose
def test_worker_runtime_is_constrained_by_environment():
dockerfile = Path("infra/docker/worker.Dockerfile").read_text(encoding="utf-8")
assert "--concurrency=${WORKER_CONCURRENCY:-1}" in dockerfile
assert "--max-tasks-per-child=${WORKER_MAX_TASKS_PER_CHILD:-100}" in dockerfile
def test_production_nginx_proxies_to_production_api_container():
config = Path("infra/docker/nginx-production.conf").read_text(encoding="utf-8")