Initial AI manga platform
This commit is contained in:
@@ -0,0 +1,622 @@
|
||||
# AI Manga Platform
|
||||
|
||||
AI 漫剧 / AI 写真视频生成平台。当前优先开发系统 A:原创小说 / 上传小说 -> 韩漫 / 漫剧生成系统。
|
||||
|
||||
## 当前阶段
|
||||
|
||||
阶段 23:API 加密传输已完成,当前进入生产化补齐。AI 原创小说 3 集 MP4 与上传小说 1 集 MP4 两条闭环已跑通,并在 HTTPS 基础上叠加前后端应用层加密信封;真实图片/TTS/视频资产落库、OpenAI Sora 视频 Provider 驱动、后台用户高危操作审计、细粒度 RBAC 和审计导出已补齐。
|
||||
|
||||
当前已完成后端基础骨架、数据库 schema、JWT 认证、私有文件上传、项目创建流程、上传小说解析、AI 原创小说 mock、故事圣经、角色圣经、长篇记忆、分集计划、单集脚本和分镜、BullMQ 队列与任务状态流转、AI Provider 抽象层、真实 AI Provider 接入、真实图片/TTS/视频资产落库、Provider 成本阈值、worker 队列消费、TTS 音频、SRT 字幕、FFmpeg 视频合成、后台管理、用户端 H5 制作台、订单额度、内容审核、MVP 验收和 API 加密传输。后台管理已覆盖项目、任务、小说源、章节、角色资源、分镜资源、成品漫剧、订单额度、内容审核、Provider、成本、用户、素材、版权记录和审计日志,并补充资源详情/媒体预览、用户人工加余额、额度冲正、用户禁用/启用、改角色、重置密码和用户详情抽屉,高危用户操作带二次确认,后台接口按 admin/operator/finance/auditor 做细粒度权限校验。用户端已支持登录注册、项目创建、原创/上传入口、版权确认、故事/角色/记忆/分集/脚本/分镜/媒体生成、额度查看/冻结、内容审核、公开案例授权、进度查看和私有成品下载;当前内部测试不展示支付/套餐入口,额度由后台人工增加。AI Provider 已支持 OpenAI 真实调用,后台可配置 API Key、Base URL、模型、优先级、启停状态、单次成本上限和当日成本上限;API Key 使用服务端密钥加密落库,页面不回显明文。图片、TTS 和 OpenAI Sora 视频生产链路已能保存真实 Provider 返回的二进制素材,默认优先级仍可保持 mock,避免未确认成本前误消耗真实模型。
|
||||
|
||||
新手操作请先看 [OPERATION_GUIDE.md](./OPERATION_GUIDE.md),里面按用户端和后台分别说明从项目创建到成品视频、额度、审核、AI 接入和常见问题排查。产品内也已补充教程入口:后台左侧“使用教程”,用户端导航“教程”,并预留 `src/pages/help/tutorial` 独立页面。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
backend/ NestJS API 服务
|
||||
admin/ Geeker-Admin 可接入的后台前端骨架
|
||||
user-app/ uni-app 路由预留、H5 优先的用户端制作台
|
||||
workers/ BullMQ / FFmpeg worker 入口
|
||||
deploy/ 本地依赖、Docker、Nginx、部署脚本预留
|
||||
docs/ 系统 A / B 需求和工程文档
|
||||
storage/ 本地 mock 存储目录
|
||||
```
|
||||
|
||||
## 本地启动
|
||||
|
||||
安装依赖:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
后端启动会自动加载根目录 `.env` 和 `backend/.env`;系统环境变量优先级最高。`PROVIDER_SECRET_KEY` 必须长期保持稳定,用于解密后台保存的 AI Provider Key。
|
||||
|
||||
启动后端空服务:
|
||||
|
||||
```bash
|
||||
npm run dev:backend
|
||||
```
|
||||
|
||||
后端默认监听:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:3000/api/health
|
||||
```
|
||||
|
||||
启动后台骨架:
|
||||
|
||||
```bash
|
||||
npm run dev:admin
|
||||
```
|
||||
|
||||
启动用户端 H5:
|
||||
|
||||
```bash
|
||||
npm run dev:user
|
||||
```
|
||||
|
||||
## 验证命令
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
npm run typecheck
|
||||
npm test
|
||||
npm run build
|
||||
```
|
||||
|
||||
## API 加密传输
|
||||
|
||||
阶段 23 已实现前后端应用层加密信封,并保留 HTTPS 作为生产必需底座。阶段 23 补充了后台配置开关:测试默认关闭,上线后可在后台“配置管理”手动开启。
|
||||
|
||||
实现范围:
|
||||
|
||||
- 前端先通过 `GET /api/client-config` 读取 `api_crypto_enabled`,默认不开启加密。
|
||||
- 开关开启后,前端通过 `GET /api/crypto/handshake` 获取短期 ECDH 会话参数。
|
||||
- 前端和后端使用 `ECDH P-256 + HKDF-SHA256` 派生会话 AES key。
|
||||
- JSON API 请求体使用 `AES-256-GCM` 加密后发送。
|
||||
- JSON API 响应体、异常响应体使用 `AES-256-GCM` 加密后返回。
|
||||
- 用户端小说上传改为加密 JSON 文件 payload,不再裸传 multipart 正文。
|
||||
- 私有素材下载在加密请求下返回加密 JSON 文件 payload,前端解密后再生成 Blob。
|
||||
- 后台和用户端生产构建默认使用同源 `/api`;显式配置 `VITE_API_BASE_URL` 时生产环境禁止 `http://`。
|
||||
- 后台管理新增“配置管理”,可维护 `security.api_crypto_enabled`。
|
||||
- `API_CRYPTO_ENABLED=true/false` 可强制覆盖数据库配置;默认 `auto` 表示读取后台配置。
|
||||
|
||||
生产建议:
|
||||
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
HTTPS_REQUIRED=true
|
||||
HTTPS_ALLOW_LOCAL_HTTP=false
|
||||
TRUST_PROXY=true
|
||||
CORS_ORIGINS=https://manga.example.com,https://admin.manga.example.com
|
||||
API_CRYPTO_ENABLED=auto
|
||||
API_CRYPTO_SESSION_TTL_SECONDS=900
|
||||
VITE_API_CRYPTO_ENABLED=auto
|
||||
VITE_API_BASE_URL=/api
|
||||
```
|
||||
|
||||
开启方式:
|
||||
|
||||
1. 保持 `API_CRYPTO_ENABLED=auto` 和 `VITE_API_CRYPTO_ENABLED=auto`。
|
||||
2. 用管理员账号进入后台“配置管理”。
|
||||
3. 点击“开启 API 加密”,之后普通 API 会强制要求加密信封。
|
||||
|
||||
注意:应用层加密保护的是请求体和响应体内容。HTTP 方法、路径、域名和查询字符串不能被前端 JS 在应用层隐藏,所以生产环境仍必须使用 HTTPS,并应避免把敏感业务内容放进 query string。多实例部署时,当前内存态加密会话需要粘性会话或迁移到 Redis。
|
||||
|
||||
## 数据库
|
||||
|
||||
阶段 02 选择 Prisma 作为 MySQL 8 ORM。原因是当前系统 A 表数量多、JSON 字段多、后续迁移频繁,Prisma 的 schema、migration 和类型生成更适合分阶段落地。
|
||||
|
||||
核心文件:
|
||||
|
||||
```text
|
||||
backend/prisma/schema.prisma
|
||||
backend/prisma/migrations/20260531093000_init_system_a/migration.sql
|
||||
backend/prisma/seed.ts
|
||||
```
|
||||
|
||||
常用命令:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
DATABASE_URL="mysql://ai_manga:ai_manga_password@127.0.0.1:3306/ai_manga" npm run db:validate
|
||||
DATABASE_URL="mysql://ai_manga:ai_manga_password@127.0.0.1:3306/ai_manga" npm run db:generate
|
||||
DATABASE_URL="mysql://ai_manga:ai_manga_password@127.0.0.1:3306/ai_manga" npm run db:migrate
|
||||
DATABASE_URL="mysql://ai_manga:ai_manga_password@127.0.0.1:3306/ai_manga" npm run db:deploy
|
||||
DATABASE_URL="mysql://ai_manga:ai_manga_password@127.0.0.1:3306/ai_manga" npm run db:seed
|
||||
```
|
||||
|
||||
`db:migrate` 用于开发环境生成/演进迁移,可能需要创建 shadow database 的权限。已有 migration 文件时,服务器环境优先使用 `db:deploy`。
|
||||
|
||||
## 认证接口
|
||||
|
||||
阶段 03 已实现基础 JWT 认证:
|
||||
|
||||
```text
|
||||
POST /api/auth/register
|
||||
POST /api/auth/login
|
||||
POST /api/auth/logout
|
||||
GET /api/auth/profile
|
||||
GET /api/profile
|
||||
```
|
||||
|
||||
`/api/auth/profile` 和 `/api/profile` 都需要 `Authorization: Bearer <token>`。
|
||||
|
||||
## 项目接口
|
||||
|
||||
阶段 05 已实现登录用户的项目创建、列表、详情、更新、取消和软删除流程:
|
||||
|
||||
```text
|
||||
POST /api/projects
|
||||
GET /api/projects
|
||||
GET /api/projects/:id
|
||||
PATCH /api/projects/:id
|
||||
POST /api/projects/:id/cancel
|
||||
DELETE /api/projects/:id
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- `input_mode` 当前支持 `ai_original` 和 `upload`,`admin_import` 预留给后台导入。
|
||||
- 新项目默认进入 `source_selecting` 状态。
|
||||
- `DELETE /api/projects/:id` 当前为软删除,会把可删除项目归档为 `archived`。
|
||||
|
||||
## 文件上传
|
||||
|
||||
阶段 04 已实现私有资产上传。当前本机未启动 MinIO 时,默认使用本地 mock 私有存储;后续将 `STORAGE_DRIVER=minio` 并配置 `MINIO_*` 即可切换。
|
||||
|
||||
```text
|
||||
POST /api/assets/upload
|
||||
POST /api/projects/:projectId/novel/upload
|
||||
GET /api/assets/:assetId
|
||||
GET /api/assets/:assetId/download
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 上传字段名为 `file`。
|
||||
- 小说上传当前支持 `txt`、`md`、`docx` 和文本型 `pdf`。
|
||||
- 上传资产默认 `visibility=private`。
|
||||
- 普通 asset 查询只返回内部 asset 信息,不返回原始文件公网地址。
|
||||
- `/api/assets/:assetId/download` 需要 Bearer Token,会校验资产归属后返回私有文件流,用户端成品下载和视频预览使用该接口。
|
||||
|
||||
## 小说解析与版权
|
||||
|
||||
阶段 06 已实现上传小说解析链路:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/copyright/confirm
|
||||
GET /api/projects/:projectId/copyright
|
||||
POST /api/projects/:projectId/novel/paste
|
||||
POST /api/projects/:projectId/novel/parse
|
||||
GET /api/projects/:projectId/novel/parse-result
|
||||
PATCH /api/novel-chapters/:chapterId
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 上传小说解析前必须先确认版权,否则 `/novel/parse` 返回 400。
|
||||
- `authorization_type` 支持 `author_self`、`licensed`、`public_domain`、`internal_test`。
|
||||
- `/novel/parse` 支持从已上传 asset 解析,也支持从粘贴文本 source 解析。
|
||||
- 解析会清洗常见广告/水印行,识别章节标题,失败时按字数切分。
|
||||
- 解析结果写入 `novel_sources` 和 `novel_chapters`。
|
||||
- 章节可手动编辑,编辑后状态标记为 `edited`。
|
||||
|
||||
## AI 原创小说 Mock
|
||||
|
||||
阶段 07 已实现 AI 原创小说 mock 链路:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/original/idea
|
||||
POST /api/projects/:projectId/original/outline
|
||||
POST /api/projects/:projectId/original/chapters
|
||||
POST /api/projects/:projectId/original/self-check
|
||||
GET /api/projects/:projectId/original/result
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 项目 `input_mode` 必须为 `ai_original`,上传小说项目调用原创接口会返回 400。
|
||||
- 当前实现为 deterministic mock,`parse_report.provider=mock_novel_provider`,不调用真实 AI Provider。
|
||||
- 生成内容写入 `novel_sources` 和 `novel_chapters`。
|
||||
- 默认按项目 `target_episode_count` 生成章节,MVP 场景通常为 3 章。
|
||||
- 自检覆盖主角一致性、主线、冲突、可视化摘要和短视频钩子。
|
||||
|
||||
## 故事圣经
|
||||
|
||||
阶段 08 已实现故事圣经链路:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/story-bible/generate
|
||||
GET /api/projects/:projectId/story-bible
|
||||
PATCH /api/projects/:projectId/story-bible
|
||||
POST /api/projects/:projectId/story-bible/confirm
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 生成前必须已有小说来源和章节,支持上传解析链路和 AI 原创 mock 链路。
|
||||
- 生成结果写入 `story_bibles`,状态为 `waiting_confirm`。
|
||||
- 编辑故事圣经会创建新版本,不覆盖旧版本。
|
||||
- 确认后故事圣经状态变为 `confirmed`,项目状态变为 `story_confirmed`。
|
||||
- `GET /story-bible?version=2` 可查询指定版本;不传 version 返回最新版本和版本列表。
|
||||
|
||||
## 角色圣经
|
||||
|
||||
阶段 09 已实现角色圣经链路:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/characters/extract
|
||||
GET /api/projects/:projectId/characters
|
||||
POST /api/projects/:projectId/characters
|
||||
POST /api/projects/:projectId/characters/confirm
|
||||
PATCH /api/characters/:characterId
|
||||
DELETE /api/characters/:characterId
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 抽取角色前必须已有已确认故事圣经,否则 `/characters/extract` 返回 400。
|
||||
- 角色抽取当前为 deterministic mock,从已确认故事圣经和小说章节生成主角、反派、配角等角色草稿。
|
||||
- 角色数据写入 `characters` 表,支持列表、手动新增、编辑和软删除。
|
||||
- 确认角色库会把 `draft`、`generated`、`edited` 状态角色锁定为 `locked`,项目状态变为 `character_confirmed`。
|
||||
- `locked` 角色不可修改姓名、角色类型、性别、年龄、身份和核心外观字段;仍可补充服装规则、表情风格等非核心描述。
|
||||
- 本阶段不生成角色图片、不生成 anchor 图,也不接入 ImageProvider 或队列。
|
||||
|
||||
## 长篇记忆
|
||||
|
||||
阶段 10 已实现长篇记忆链路:
|
||||
|
||||
```text
|
||||
GET /api/projects/:projectId/plot-memories
|
||||
POST /api/projects/:projectId/plot-memories/generate
|
||||
POST /api/projects/:projectId/plot-memories
|
||||
PATCH /api/plot-memories/:memoryId
|
||||
GET /api/projects/:projectId/memory-context?episode_no=5
|
||||
GET /api/characters/:characterId/memories
|
||||
GET /api/projects/:projectId/plot-threads
|
||||
POST /api/projects/:projectId/plot-threads
|
||||
PATCH /api/plot-threads/:threadId
|
||||
POST /api/episodes/:episodeId/continuity-check
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 生成长篇记忆前必须已有 confirmed 故事圣经和 locked 角色库。
|
||||
- 记忆生成当前为 deterministic mock,会写入 `plot_memories`、`plot_threads` 和 `character_memories`。
|
||||
- 剧情记忆支持手动新增、标记 resolved/archived、按类型/状态/分集筛选。
|
||||
- 剧情线支持新增、查询、更新状态,类型覆盖主线、反派计划、悬疑线、角色成长线等。
|
||||
- `GET /memory-context?episode_no=N` 会返回故事圣经、锁定角色、活跃剧情记忆、开放剧情线、前 3 集摘要和上一集结尾钩子,供后续分集/脚本生成使用。
|
||||
- locked 角色的非核心资料补充会自动记录 `character_memories.profile_adjustment`。
|
||||
- 连续性检查当前为规则版 mock,可发现角色未承接、伏笔未推进、上一集钩子未承接、缺少结尾钩子、开放剧情线未推进和明显破坏世界观的内容。
|
||||
- 本阶段不接入 EmbeddingProvider、不做向量检索、不进队列,也不调用真实 AI Provider。
|
||||
|
||||
## 分集计划
|
||||
|
||||
阶段 11 已实现分集计划链路:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/episodes/generate-plan
|
||||
GET /api/projects/:projectId/episodes
|
||||
PATCH /api/episodes/:episodeId
|
||||
POST /api/projects/:projectId/episodes/confirm
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 生成分集前必须已有 confirmed 故事圣经、locked 角色库、小说章节和 active 长篇记忆。
|
||||
- 分集生成当前为 deterministic mock,会写入 `episodes` 表。
|
||||
- 每集包含标题、剧情摘要、开头钩子、中段冲突、结尾悬念、关联章节和预计时长。
|
||||
- 生成时项目状态流转为 `episode_planning`,完成后为 `waiting_episode_confirm`。
|
||||
- 分集可在确认前编辑,编辑后状态为 `edited`。
|
||||
- 确认分集会把 `draft`、`generated`、`edited` 状态分集锁定为 `confirmed`,项目状态变为 `episode_confirmed`。
|
||||
- 已确认分集不可继续编辑;如需重做,后续会通过返工/修改申请流程处理。
|
||||
- 本阶段不生成单集脚本、不生成分镜、不进队列,也不调用真实 AI Provider。
|
||||
|
||||
## 脚本和分镜
|
||||
|
||||
阶段 12 已实现单集脚本和分镜链路:
|
||||
|
||||
```text
|
||||
POST /api/episodes/:episodeId/script/generate
|
||||
GET /api/episodes/:episodeId/script
|
||||
PATCH /api/episodes/:episodeId/script
|
||||
POST /api/episodes/:episodeId/script/confirm
|
||||
POST /api/episodes/:episodeId/storyboard/generate
|
||||
GET /api/episodes/:episodeId/storyboard
|
||||
PATCH /api/storyboard-shots/:shotId
|
||||
DELETE /api/storyboard-shots/:shotId
|
||||
POST /api/episodes/:episodeId/storyboard/confirm
|
||||
POST /api/storyboard-shots/:shotId/regenerate-prompt
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 生成单集脚本前必须已有 confirmed 分集、confirmed 故事圣经和 locked 角色库。
|
||||
- 单集脚本当前为 deterministic mock,会写入 `episode_scripts`,包含脚本文本、旁白和结构化台词。
|
||||
- 脚本生成后项目状态进入 `waiting_script_confirm`;确认后脚本状态为 `confirmed`,项目状态为 `script_confirmed`。
|
||||
- 生成分镜前必须已有 confirmed 单集脚本。
|
||||
- 分镜生成当前为 deterministic mock,会写入 `storyboard_shots`,默认每集 10 个镜头。
|
||||
- 每个镜头包含画面描述、人物、场景、动作、台词/旁白、镜头运动、特效、2-5 秒时长、Prompt 和负面 Prompt。
|
||||
- Prompt 会带入角色固定描述,并包含防混脸、年龄/发色漂移、复杂多人镜头等负面约束。
|
||||
- 分镜可在确认前编辑、删除和重生 Prompt;确认后镜头状态为 `confirmed`,项目状态为 `storyboard_confirmed`。
|
||||
- 本阶段不生成分镜图片、不接入 ImageProvider、不进队列,也不调用真实 AI Provider。
|
||||
|
||||
## BullMQ 队列
|
||||
|
||||
阶段 13 已实现任务记录、幂等入队、管理员重试/取消/人工介入和队列监控:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/tasks
|
||||
GET /api/projects/:projectId/tasks
|
||||
GET /api/tasks/:taskId
|
||||
GET /api/admin/tasks
|
||||
POST /api/admin/tasks/recover-stale
|
||||
POST /api/admin/tasks/:taskId/retry
|
||||
POST /api/admin/tasks/:taskId/cancel
|
||||
POST /api/admin/tasks/:taskId/manual-required
|
||||
GET /api/admin/queues
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 普通用户只能操作自己的项目任务,admin 可查看和管理全部任务。
|
||||
- 创建任务会先写入 `render_tasks`,再尝试入 BullMQ;Redis 或 BullMQ 不可用时,任务仍保留为 `pending` / `retrying`,接口返回 `queue_backend=bullmq_unavailable`。
|
||||
- 幂等 key 默认由 `project_id + episode_id + shot_id + task_type + input_hash` 组成,`input_hash` 基于稳定 JSON 序列化生成。
|
||||
- 已支持 novel、parse、story、character、episode、script、storyboard、image、audio、subtitle、video、qc、review、analytics 等队列映射。
|
||||
- 默认重试次数按任务类型区分:文本类 2 次、图片类 3 次、视频 2 次、TTS/字幕 2 次、QC 1 次、人工审核 0 次。
|
||||
- 管理员可把失败任务重试为 `retrying`,可取消任务为 `cancelled`,可标记为 `manual_required`,可恢复过久未完成的 `running` / `retrying` 任务。
|
||||
- `/api/admin/queues` 会返回 BullMQ 每个队列的 waiting、active、delayed、failed、completed、paused 计数。
|
||||
- worker 包已接入 BullMQ 消费器,会订阅全部队列并调用后端内部接口 `POST /api/internal/worker/tasks/:taskId/execute`,通过 `WORKER_SECRET` 鉴权。
|
||||
- worker 执行失败时后端会按 `max_retry` 自动重入队;达到上限后把任务转为 `manual_required`,后台任务页可继续人工处理。
|
||||
- worker 当前执行的是通用 Provider 任务委托:按任务类型映射到 Text/Novel/Image/Voice/Video/Moderation/QC/FileParse Provider;图片、音频、视频资产生成的业务接口仍保留同步链路。
|
||||
|
||||
## AI Provider 抽象
|
||||
|
||||
阶段 14 已实现 mock-first Provider 抽象、管理员配置入口、执行日志和成本聚合;阶段 21 已补充 OpenAI / OpenAI 兼容真实驱动:
|
||||
|
||||
```text
|
||||
GET /api/admin/providers
|
||||
POST /api/admin/providers/bootstrap-mocks
|
||||
POST /api/admin/providers/bootstrap-openai
|
||||
POST /api/admin/providers/bootstrap-video
|
||||
POST /api/admin/providers/execute
|
||||
PATCH /api/admin/providers/:providerId
|
||||
PATCH /api/admin/providers/openai/runtime-config
|
||||
PATCH /api/admin/providers/:providerId/runtime-config
|
||||
POST /api/admin/providers/:providerId/test
|
||||
GET /api/admin/provider-logs
|
||||
GET /api/admin/costs
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`;后台接口按 RBAC 权限校验,admin 拥有全部权限,operator/finance/auditor 只开放对应读写范围。
|
||||
- 已声明 `TextProvider`、`NovelProvider`、`ImageProvider`、`VideoProvider`、`VoiceProvider`、`ModerationProvider`、`QualityCheckProvider`、`FileParseProvider`、`EmbeddingProvider`。
|
||||
- `/bootstrap-mocks` 会写入或更新 9 个默认 mock provider 配置。
|
||||
- `/bootstrap-openai` 会写入或更新 OpenAI real provider 配置,包含 Responses、Moderation、Embeddings、Image Generation、Sora Video 和 Text to Speech 驱动。
|
||||
- 后台默认显示“OpenAI 统一接入”:运营只需填写一个 OpenAI API Key,`PATCH /admin/providers/openai/runtime-config` 会批量应用到全部 OpenAI 能力;未勾选“生产任务优先使用 OpenAI”时会把 OpenAI 优先级保持为 50,低于 mock,避免保存 Key 后立刻消耗真实额度。
|
||||
- `GET /admin/providers/openai/connection-check` 只请求 OpenAI `/models` 检查 Key/网络,不生成文本、图片、语音或视频,不写 `provider_logs`。
|
||||
- `/execute` 会从 `provider_configs` 选择启用 provider,执行 mock 或 real driver,写入 `provider_logs`。
|
||||
- 如果传入 `task_id`,执行时会把对应 `render_tasks` 标记为 `running`,成功后回写 `success`、`provider_id`、`provider_request_id`、`cost_estimate` 和 `cost_actual`。
|
||||
- primary provider 失败时会按 fallback provider 或同类型优先级继续尝试,并记录失败日志。
|
||||
- provider 输入、配置输出和日志输出会拒绝/脱敏 `api_key`、`secret`、`token`、`password`、`credential` 等疑似密钥字段;后台运行配置接口会把 API Key 加密为 `api_key_secure` 后保存,列表只显示已配置状态。
|
||||
- 真实 Provider 优先读取后台加密保存的 API Key;未配置时仍可回退读取 `OPENAI_API_KEY`。后台可配置 `base_url` 接入 OpenAI 兼容服务,也可修改模型名、优先级和启停状态。`PROVIDER_SECRET_KEY` 用于加密后台保存的 Provider 密钥,未设置时回退 `JWT_SECRET`;生产环境必须保持该值稳定,否则已保存 Key 无法解密,需要重新保存。
|
||||
- 重复点击“初始化 OpenAI 接入”会刷新默认 Provider 定义,但会保留后台已加密保存的 API Key、Base URL、超时和成本阈值,避免误清空线上配置。
|
||||
- 后台真实 Provider 的“付费测试”必须二次确认,后端 `/admin/providers/:providerId/test` 也要求 `confirm_paid_test=true`;真实视频 Provider 测试接口默认禁用,避免误触发高成本视频任务。
|
||||
- Provider 可配置 `max_cost_per_call` 和 `daily_cost_limit` 成本阈值,也可通过 `PROVIDER_MAX_COST_PER_CALL`、`PROVIDER_DAILY_COST_LIMIT` 设置全局保护;超过阈值会在调用前拦截并写失败日志。
|
||||
- `openai_image_generation`、`openai_video_generation` 和 `openai_audio_speech` 的日志只保存 URL/大小/hash 等元数据,不把 base64 图片、视频或音频字节写入 `provider_logs`;真实二进制只在业务生成链路中短暂返回,用于立即写入私有素材。
|
||||
- OpenAI 图片、Sora 视频和 TTS real provider 默认优先级低于 mock;后台可提高优先级或禁用 mock 后让业务生产链路保存真实图片、真实视频或 TTS 音频资产。
|
||||
- `openai_video_generation` 按 OpenAI Videos API 的异步流程执行:创建视频任务、轮询完成状态,业务链路需要二进制时再下载 MP4 并落库。可用 `OPENAI_VIDEO_MODEL` 覆盖默认 `sora-2`。
|
||||
- 真人短剧链路已新增可替换 image-to-video Provider:`minimax_hailuo_23_fast`、`minimax_hailuo_23`、`alibaba_wan26_i2v_flash`、`alibaba_wan26_i2v`、`vidu_q3_turbo_reference`、`vidu_q3_pro`、`jimeng_seedance`、`runway-image-to-video`、`kling-image-to-video`。真实视频 Provider 默认禁用,用户端真实视频生成必须传 `confirm_real_video=true`,并受单片段成本上限、Provider 单次/每日成本阈值保护。
|
||||
- `configurable_image_to_video` 驱动支持通用异步图生视频流程:创建任务、轮询任务、提取视频 URL;如果供应商只返回 `file_id`,可通过 `output_url_endpoint_template` 再取下载链接。MiniMax Hailuo、阿里 Wan、Vidu 和 Seedance 预设都走这类可配置模板,正式启用前应先用 1 个镜头小样核对字段、速度、质量和账单。
|
||||
- `VideoProvider` 成本规则支持 `unit=video_seconds`、`price_per_second`、`price_per_clip`。后台配置真实视频价格后,用户端真人短剧面板会显示片段级成本预估。
|
||||
|
||||
## 图片生成 Mock
|
||||
|
||||
阶段 15 已实现角色图、锚点图、分镜预览图和正式图的 mock 生成:
|
||||
|
||||
```text
|
||||
POST /api/characters/:characterId/generate-images
|
||||
GET /api/characters/:characterId/images
|
||||
POST /api/characters/:characterId/set-anchor
|
||||
POST /api/storyboard-shots/:shotId/images/generate
|
||||
GET /api/storyboard-shots/:shotId/images
|
||||
POST /api/episodes/:episodeId/shot-images/generate
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 角色图生成要求角色已 `locked`。
|
||||
- 默认生成 `front_reference`、`anchor`、`expression_pack`,也可指定 `image_types`。
|
||||
- 角色锚点会写入 `character_images.is_anchor=true`,并回写 `characters.anchor_asset_id`。
|
||||
- 分镜图生成要求 `storyboard_shots.status=confirmed`。
|
||||
- 分镜图 Prompt 会引用角色固定描述和 `anchor_asset_id`,降低混脸和漂移风险。
|
||||
- 图片生成会创建 `render_tasks`,通过 `ImageProvider` 执行,写入 `provider_logs`,并保存本地/MinIO 私有图片资产。
|
||||
- 生成结果写入 `character_images` 或 `shot_images`,图片资产写入 `assets`,`visibility=private`。
|
||||
- 当 Provider 返回 `content_base64` 或可下载的 HTTP(S) `asset_url` 时,会保存真实位图;否则回退生成 SVG mock 占位图。图片任务会回填 `render_tasks.output_asset_id`,方便后台追踪产物。
|
||||
|
||||
## TTS / 字幕 / FFmpeg
|
||||
|
||||
阶段 16 已实现单集音频、字幕和 FFmpeg 视频合成链路:
|
||||
|
||||
```text
|
||||
POST /api/episodes/:episodeId/audio/generate
|
||||
POST /api/episodes/:episodeId/subtitle/generate
|
||||
POST /api/episodes/:episodeId/video/render
|
||||
GET /api/episodes/:episodeId/media-assets
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`。
|
||||
- 音频生成要求已有 `confirmed` 单集脚本,会调用 `VoiceProvider`,写入 `render_tasks`、`provider_logs` 和私有音频资产;真实 TTS 返回 `content_base64` 或可下载 URL 时保存真实音频,否则回退静音 WAV。
|
||||
- 字幕生成要求已有 `confirmed` 分镜,会按镜头时长生成 SRT cues,写入本地私有 `.srt` 资产。
|
||||
- 视频渲染要求已有 `confirmed` 分镜和已生成的分镜图;默认会复用或自动生成最新音频和字幕。
|
||||
- 视频渲染要求项目已支付或冻结额度,否则会返回错误;阶段 19 用户端会在合成前调用额度冻结。
|
||||
- 视频渲染会调用 `VideoProvider` 记录 provider 执行日志;若启用 `openai-video`,后端会创建 Sora 视频任务、轮询完成并下载 MP4,随后直接保存 Provider 渲染出的 MP4;若 Provider 未返回二进制,则读取私有分镜图、音频和 SRT 字幕,使用 FFmpeg 生成本地私有 MP4 资产。
|
||||
- 默认优先使用 FFmpeg,成功时返回 `ffmpeg_used=true` 和 `render_backend=ffmpeg`;传入 `prefer_ffmpeg=false` 或本机缺少 FFmpeg 时会走 mock fallback。
|
||||
- 生成结果写入 `assets`,asset_type 分别为 `audio`、`subtitle`、`video`,`visibility=private`。
|
||||
- 当前不生成真实 BGM;图片、TTS 和 Sora 视频可切换真实 Provider 落库,视频也可保留 FFmpeg 本地合成,音频、字幕和视频目前仍为同步接口执行,worker 消费器后续接入。
|
||||
|
||||
## 后台管理
|
||||
|
||||
阶段 17 已实现后台管理 API 和可用的 Vue/Vite 管理端:
|
||||
|
||||
```text
|
||||
GET /api/admin/dashboard
|
||||
GET /api/admin/rbac/me
|
||||
GET /api/admin/projects
|
||||
GET /api/admin/projects/:projectId
|
||||
PATCH /api/admin/projects/:projectId/status
|
||||
GET /api/admin/users
|
||||
GET /api/admin/assets
|
||||
GET /api/admin/novel-sources
|
||||
GET /api/admin/novel-chapters
|
||||
GET /api/admin/characters
|
||||
GET /api/admin/storyboard-shots
|
||||
GET /api/admin/works
|
||||
GET /api/admin/copyright-records
|
||||
GET /api/admin/operation-logs
|
||||
GET /api/admin/operation-logs/export
|
||||
```
|
||||
|
||||
已接入已有管理接口:
|
||||
|
||||
```text
|
||||
GET /api/admin/tasks
|
||||
POST /api/admin/tasks/:taskId/retry
|
||||
POST /api/admin/tasks/:taskId/cancel
|
||||
POST /api/admin/tasks/:taskId/manual-required
|
||||
GET /api/admin/queues
|
||||
GET /api/admin/providers
|
||||
POST /api/admin/providers/bootstrap-mocks
|
||||
GET /api/admin/provider-logs
|
||||
GET /api/admin/costs
|
||||
GET /api/admin/orders
|
||||
GET /api/admin/quota-accounts
|
||||
GET /api/admin/users/:userId/detail
|
||||
POST /api/admin/users/:userId/quota/grant
|
||||
GET /api/admin/content-reviews
|
||||
PATCH /api/admin/content-reviews/:reviewId
|
||||
GET /api/admin/case-showcases
|
||||
PATCH /api/admin/case-showcases/:showcaseId
|
||||
GET /api/admin/system-configs
|
||||
PATCH /api/admin/system-configs/:configKey
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 请求必须带 `Authorization: Bearer <token>`;后台支持 `admin`、`operator`、`finance`、`auditor` 角色,接口按 `projects/users/billing/reviews/tasks/providers/costs/settings/audit` 等权限校验。
|
||||
- `npm run db:seed` 会创建或更新本地 `admin@example.com`,默认开发密码为 `Admin123!`,可用 `SEED_ADMIN_PASSWORD` 覆盖。
|
||||
- 管理端默认运行在 `http://127.0.0.1:5175`,API 默认指向 `http://127.0.0.1:3000/api`,可用 `VITE_API_BASE_URL` 覆盖。
|
||||
- 当前后台已支持登录、仪表盘、项目管理、项目详情、项目状态调整、小说源/章节管理、角色资源、分镜资源、成品漫剧、订单额度、内容审核、公开案例授权、任务重试/取消/转人工、队列统计、Provider 配置、Provider 成本阈值、成本日志、用户列表、用户详情抽屉、用户人工加余额、额度冲正、禁用/启用用户、改角色、重置密码、素材列表、版权记录、系统配置管理和审计日志导出;小说、章节、角色、分镜、素材和成品资源支持详情/预览,高危用户操作在页面上会弹出二次确认。
|
||||
- 模板管理深水区留到后续对应阶段继续扩展。
|
||||
|
||||
## 订单额度
|
||||
|
||||
阶段 19 已实现订单、额度账户和项目正式生成前冻结/扣减:
|
||||
|
||||
```text
|
||||
GET /api/billing/packages
|
||||
GET /api/billing/quota
|
||||
GET /api/billing/quota/logs
|
||||
GET /api/billing/orders
|
||||
POST /api/billing/orders
|
||||
POST /api/billing/orders/:orderId/mock-pay
|
||||
GET /api/projects/:projectId/quota/estimate
|
||||
POST /api/projects/:projectId/quota/freeze
|
||||
POST /api/projects/:projectId/quota/release
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- `/api/billing/packages` 可公开查看,其他用户额度接口需要 Bearer Token。
|
||||
- 当前为内部测试额度模式:用户端不展示支付/套餐入口,运营在后台用户管理中人工增加额度。历史 mock 支付接口仍保留用于接口回归,不作为当前用户端入口。
|
||||
- 项目额度预估按输入模式、目标集数和默认每集 6 个镜头估算。
|
||||
- `quota/freeze` 会扣减可用额度、增加冻结额度,并把项目 `payment_status` 标记为 `quota_frozen`。
|
||||
- 视频合成成功后会把冻结额度扣为已用额度,并把项目 `payment_status` 标记为 `paid`。
|
||||
- 管理端新增“订单额度”页,可查看订单和额度账户;用户管理页支持管理员手动给用户增加余额/额度和执行额度冲正,并写入额度流水和操作日志,用户详情抽屉可查看额度流水、订单、项目、素材和最近操作。
|
||||
|
||||
## 内容审核
|
||||
|
||||
阶段 20 已实现文本、素材、成品视频和公开案例授权的审核闭环:
|
||||
|
||||
```text
|
||||
POST /api/projects/:projectId/reviews/text
|
||||
GET /api/projects/:projectId/reviews
|
||||
POST /api/assets/:assetId/review
|
||||
POST /api/projects/:projectId/showcase/authorize
|
||||
GET /api/projects/:projectId/showcase
|
||||
GET /api/admin/content-reviews
|
||||
PATCH /api/admin/content-reviews/:reviewId
|
||||
GET /api/admin/case-showcases
|
||||
PATCH /api/admin/case-showcases/:showcaseId
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 用户接口必须带 Bearer Token,并校验项目或素材归属。
|
||||
- 文本审核会聚合项目中的小说、故事圣经、角色、分集、脚本和分镜文本,也支持请求体直接传入 `content`。
|
||||
- 素材审核覆盖 image、video、audio、subtitle 和 document/text 类资产;用户端当前接入文本审核和成品视频审核按钮。
|
||||
- 审核调用现有 `ModerationProvider`;未初始化真实 Provider 时使用 mock,初始化 OpenAI 接入并在后台保存 API Key 后会优先调用 `openai-moderation`,失败时回退 mock。
|
||||
- 需要人工处理的审核会把项目状态标记为 `manual_required`,后台可执行通过、修改、驳回、屏蔽和转人工。
|
||||
- 用户端可提交公开案例授权,后台可将案例授权、发布为 public 或驳回。
|
||||
- 当前不接入真实内容安全平台,不做真实版权库比对;商业发布前仍需人工确认版权授权、平台规则和内容合规。
|
||||
- mock moderation 会识别“不得/禁止/避免违法内容”这类安全规则提示,不再把合规约束本身误判为风险文本。
|
||||
|
||||
## MVP 验收
|
||||
|
||||
阶段 22 已完成系统 A MVP 端到端验收:
|
||||
|
||||
- AI 原创小说链路:原创构思、章节、故事圣经、角色、角色锚点、长篇记忆、3 集分集、脚本、分镜、正式分镜图、音频、字幕、FFmpeg MP4、私有下载、视频审核和案例授权。
|
||||
- 上传小说链路:TXT 上传、版权确认、小说解析、故事圣经、角色、角色锚点、长篇记忆、1 集分集、脚本、分镜、正式分镜图、音频、字幕、FFmpeg MP4、私有下载、视频审核和案例授权。
|
||||
- 验收用户 `mvp-1780243409631@example.com`,原创项目 ID `28`,上传项目 ID `29`。
|
||||
- 原创 3 个 MP4 与上传 1 个 MP4 均通过私有下载校验,返回 `video/mp4`,文件大小均大于 300 KB。
|
||||
- 额度流程通过 mock 支付、项目冻结、视频成功后扣减;验收后账户 `used_quota=196`、`available_quota=1004`。
|
||||
- 验收时发现并修复 mock 文本审核误伤安全规则提示的问题;复审记录 `13`、`14` 均为 `passed`。
|
||||
|
||||
## 用户端 H5
|
||||
|
||||
阶段 18 已实现 H5 优先、PC 自适应的用户端制作台,并保留 uni-app `pages.json`、`manifest.json` 和页面路由文件,后续微信小程序/App 可继续迁移:
|
||||
|
||||
```text
|
||||
登录 / 注册
|
||||
新建项目
|
||||
我的项目
|
||||
制作台
|
||||
生成进度
|
||||
成品漫剧
|
||||
用户中心
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 用户端 API 可用 `VITE_API_BASE_URL` 覆盖;未配置时,本机访问会请求 `http://127.0.0.1:3000/api`,外网 IP/域名访问会自动请求同主机的 `:3000/api`。
|
||||
- 用户端默认运行在 `http://127.0.0.1:5174`。
|
||||
- 公网调试访问需要服务器防火墙/安全组放行 TCP `5174` 和 `3000`;当前本机 firewalld 已放行这两个端口。
|
||||
- H5 为主布局,移动端底部导航和单列长表单优先;PC 宽屏自动切换为左侧导航和两栏制作台。
|
||||
- 当前用户端已接入真实 API:认证、项目列表/创建、AI 原创小说、上传小说粘贴/文件入口、版权确认、故事圣经、角色库、长篇记忆、分集计划、单集脚本、分镜、分镜图、音频、字幕、FFmpeg 视频合成、任务进度、私有视频预览和下载。
|
||||
- 阶段 19 已接入额度中心;当前用户端隐藏套餐、模拟支付和订单入口,仅展示额度账户、项目额度预估和合成前冻结额度。
|
||||
- 阶段 20 已接入内容审核中心:项目文本审核、成品视频审核、审核状态列表和公开案例授权。
|
||||
- 微信小程序/App 的文件选择、下载保存、支付能力、分享能力留到后续平台适配阶段;当前内部测试不开放用户端支付入口,图片/TTS 生产链路可切换真实 Provider,视频默认仍可用 FFmpeg 本地合成。
|
||||
|
||||
## 开发约束
|
||||
|
||||
- 按 `AGENTS.md` 和 `docs/system_a/21_Codex开发任务拆解文档.md` 分阶段开发。
|
||||
- 真实 AI Provider 已接入执行层;原创小说、故事圣经、角色、记忆、分集、脚本、分镜等 deterministic 生成服务后续可逐步迁移到统一 Provider 调用。
|
||||
- 密钥只放 `.env`,不要提交真实密钥。
|
||||
- 用户上传小说和素材默认私有。
|
||||
- 每个阶段完成后更新 `CODEX_PROGRESS.md`。
|
||||
Reference in New Issue
Block a user