Files
ai/README.md
T
2026-06-15 17:45:28 +08:00

623 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`,再尝试入 BullMQRedis 或 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`