Files
ai/CURRENT_ARCHITECTURE.md

920 lines
31 KiB
Markdown
Raw Permalink 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.
# CURRENT_ARCHITECTURE
扫描时间:2026-06-17
范围:`backend``user-app``admin``workers``backend/prisma``deploy``tools`
说明:本文只记录当前项目结构、实现状态和关键路径,不包含任何 Provider 密钥。
## 1. 系统整体架构图
```mermaid
flowchart TB
User[用户前台\nllzai.top\nVue 3 + Vite] --> Nginx[Nginx / 宝塔站点]
Admin[管理后台\nai.admin.llzai.top\nVue 3 + Vite] --> Nginx
Nginx --> API[后端 API\nai.api.llzai.top\nNestJS /api]
API --> Auth[Auth / User / RBAC]
API --> Project[Projects / Workflow]
API --> Novel[Novel Library / Reader]
API --> Story[StoryBible / Episode / Script / Storyboard]
API --> Character[Character Library / Actor Profile]
API --> Live[Live Action Pipeline]
API --> Provider[AI Provider Layer]
API --> Media[Media / FFmpeg Render]
API --> AdminApi[Admin / Ops / Provider Config]
API --> Billing[Billing / Quota / Provider Cost]
API --> Prisma[Prisma ORM]
Prisma --> MySQL[(MySQL)]
API --> Redis[(Redis)]
Redis --> BullMQ[BullMQ Queues]
Worker[workers\nBullMQ Worker] --> BullMQ
Worker --> InternalAPI[/api/internal/worker/tasks/:id/execute]
InternalAPI --> API
API --> Storage[StorageService\nLocal / MinIO / Public Temp URL]
Storage --> Files[(storage / object files)]
Provider --> OpenAI[OpenAI]
Provider --> Volc[火山 / 豆包]
Provider --> Kling[可灵 Kling]
Provider --> MiniMax[MiniMax / 海螺]
Provider --> Domestic[DeepSeek / 通义 / Kimi / 智谱等]
Provider --> Mock[Mock Providers]
Live --> FFmpeg[FFmpeg / FFprobe]
Media --> FFmpeg
FFmpeg --> FinalVideo[成品视频 / 素材库]
```
真人短剧主流程:
```mermaid
flowchart LR
Prompt[外部提示词 / 小说章节 / 项目设定] --> Parse[提示词拆镜 / 分镜草稿]
Parse --> Project[创建 Project / Episode / StoryBible]
Project --> Prepare[真人分镜准备\nTextProvider 可选]
Prepare --> Keyframe[关键帧生成\nImageProvider 可选]
Keyframe --> Video[视频片段生成\nVideoProvider 可选]
Video --> Select[每个分镜选择候选片段]
Select --> Render[FFmpeg 合成]
Render --> Works[作品列表 / 素材列表]
```
小说主流程:
```mermaid
flowchart LR
Import[后台导入小说\n粘贴 / 批量 / 文件] --> Split[章节自动切割]
Split --> NovelSource[NovelSource]
Split --> Chapter[NovelChapter]
NovelSource --> Reader[前台小说详情 / 目录 / 阅读器]
Reader --> Progress[阅读进度]
Reader --> Bookmark[书签]
Reader --> Annotation[批注]
NovelSource --> ShortDrama[选择小说生成短剧]
```
## 2. 核心模块
### 后端 Backend
入口:
- `backend/src/main.ts`:全局 `/api` 前缀、CORS、请求体大小、全局拦截器、异常过滤器。
- `backend/src/app.module.ts`:注册全部业务模块。
核心模块:
- `AuthModule`:登录、JWT、权限守卫。
- `UsersModule`:用户资料和账号信息。
- `BillingModule`:订单、额度、Provider 消耗记录。
- `ProjectsModule`:项目创建、提示词直出分镜、作品库、小说库前台接口。
- `AssetsModule`:文件上传、素材存储、临时公网访问。
- `NovelsModule`:小说导入、解析、章节管理、原创小说工具。
- `StoryBiblesModule`:故事圣经、世界观设定。
- `CharactersModule`:项目角色库、我的真人脸包、角色定妆版本、状态变体。
- `MemoriesModule`:剧情记忆、连续性。
- `EpisodesModule`:分集。
- `ScriptsModule`:脚本、分镜。
- `ImagesModule`:角色图、关键帧、锚点图生成。
- `LiveActionModule`:真人短剧全流程。
- `MediaModule`:传统音频、字幕、视频合成。
- `ProvidersModule`AI Provider 注册、调用、配置、日志、成本。
- `QueuesModule`RenderTask、BullMQ 队列、内部 Worker 执行入口。
- `ReviewsModule`:内容审核、返修、案例展示。
- `AdminModule`:后台用户、项目、素材、小说、Provider、Router、运营数据。
### 前端 User App
- 技术栈:Vue 3 + Vite。
- 主要页面:`user-app/src/pages/index/index.vue`
- 主要能力:作品列表、视频/小说/素材 Tab、提示词直出分镜、真人短剧流程、模型选择、素材预览、小说阅读器、我的真人脸包。
### 后台 Admin
- 技术栈:Vue 3 + Vite。
- 主要页面:`admin/src/App.vue`
- 主要能力:Provider 配置、模型开关、成本规则、小说管理、章节管理、素材管理、用户项目管理、运营看板。
### Worker
- `workers/src/main.ts`BullMQ Worker 进程。
- Worker 不直接写复杂业务,主要从队列拿 `RenderTask`,再调用后端内部接口执行。
## 3. 数据表关系
当前 Prisma Schema 以 `*_id` 字段做逻辑关联,很多模型没有声明 Prisma `@relation`。下面是业务关系视图,不代表数据库里已经全部建外键约束。
```mermaid
erDiagram
User ||--o{ Project : owns
User ||--o{ NovelReadingProgress : reads
User ||--o{ NovelBookmark : bookmarks
User ||--o{ NovelAnnotation : annotates
User ||--o{ GlobalCharacter : owns
Project ||--o{ StoryBible : has
Project ||--o{ WorldBible : has
Project ||--o{ Character : has
Project ||--o{ Episode : has
Project ||--o{ Asset : has
Project ||--o{ CopyrightRecord : has
Project ||--o{ RenderTask : has
Project ||--o{ ActorProfile : has
NovelSource ||--o{ NovelChapter : has
NovelSource ||--o{ NovelReadingProgress : has
NovelSource ||--o{ NovelBookmark : has
NovelSource ||--o{ NovelAnnotation : has
Episode ||--o{ EpisodeScript : has
Episode ||--o{ StoryboardShot : has
Episode ||--o{ VideoClip : has
StoryboardShot ||--o{ ShotImage : has
StoryboardShot ||--o{ VideoClip : candidates
Character ||--o{ CharacterImage : has
Character ||--o{ CharacterMemory : has
Character ||--o{ CharacterDesignVersion : has
Character ||--o{ CharacterState : has
GlobalCharacter ||--o{ GlobalCharacterAsset : has
GlobalCharacter ||--o{ Character : binds
ProviderConfig ||--o{ ProviderLog : logs
ProviderConfig ||--o{ RenderTask : used_by
Asset ||--o{ VideoClip : stores
```
核心表分组:
| 分组 | 表 |
| --- | --- |
| 用户 / 项目 | `User`, `Project`, `CopyrightRecord` |
| 小说 / 阅读 | `NovelSource`, `NovelChapter`, `NovelReadingProgress`, `NovelBookmark`, `NovelAnnotation` |
| 故事世界 | `StoryBible`, `WorldBible` |
| 角色 | `Character`, `GlobalCharacter`, `GlobalCharacterAsset`, `CharacterImage`, `CharacterMemory`, `CharacterDesignVersion`, `CharacterState`, `ActorProfile` |
| 分集 / 分镜 | `Episode`, `EpisodeScript`, `StoryboardShot`, `ShotImage` |
| 视频 / 素材 | `VideoClip`, `Asset`, `RenderTask` |
| Provider / 成本 | `ProviderConfig`, `ProviderLog`, `Order`, `QuotaAccount`, `QuotaLog` |
| 审核 / 运营 | `RevisionRequest`, `ContentReview`, `CaseShowcase`, `OperationLog`, `SystemConfig` |
| 爆款分析 | `HitAnalysisCase`, `HitAnalysisSegment`, `CreativePattern`, `ProjectCreativePattern`, `AnalyticsEvent` |
重要唯一约束和索引:
- `NovelChapter``novel_source_id + chapter_no` 唯一,支持章节分页和卷号索引。
- `NovelReadingProgress``user_id + novel_source_id` 唯一。
- `CharacterDesignVersion``character_id + version_no` 唯一。
- `CharacterState``character_id + state_code` 唯一。
- `Episode``project_id + episode_no` 唯一。
- `StoryboardShot``episode_id + shot_no` 唯一。
- `ActorProfile``project_id + character_id` 唯一。
- `ProviderConfig``provider_type + provider_code` 唯一。
- `RenderTask``idempotency_key` 唯一。
- `ProjectCreativePattern``project_id + creative_pattern_id` 唯一。
## 4. AI Provider 列表
Provider 配置来自 `ProviderConfig` 表和初始化配置。状态按当前扫描结果记录。
### Provider 类型统计
| 类型 | 总数 | 启用 |
| --- | ---: | ---: |
| `TextProvider` | 35 | 26 |
| `NovelProvider` | 15 | 9 |
| `ImageProvider` | 11 | 5 |
| `VideoProvider` | 21 | 10 |
| `VoiceProvider` | 5 | 2 |
| `LipSyncProvider` | 8 | 0 |
| `EmbeddingProvider` | 2 | 2 |
| `ModerationProvider` | 2 | 2 |
| `FileParseProvider` | 1 | 1 |
| `QualityCheckProvider` | 1 | 1 |
### TextProvider
已启用:
| Provider | 显示名 | 模型 |
| --- | --- | --- |
| `volcengine-doubao-seed20-pro-text` | 豆包文本 2.0 Pro | `doubao-seed-2-0-pro-260215` |
| `volcengine-doubao-seed20-lite-text` | 豆包文本 2.0 Lite | `doubao-seed-2-0-lite-260215` |
| `volcengine-doubao-seed20-mini-text` | 豆包文本 2.0 Mini | 当前配置 |
| `volcengine-doubao-text` | 豆包文本 | `doubao-seed-1-6-250615` |
| `deepseek-text` | DeepSeek | `deepseek-chat` |
| `qwen-text` | 通义千问 | `qwen-plus` |
| `kimi-text` | Kimi | `kimi-latest` |
| `zhipu-glm-text` | 智谱 GLM | `glm-4.5` |
| `baidu-qianfan-text` | 百度千帆 | 当前配置 |
| `tencent-hunyuan-text` | 腾讯混元 | 当前配置 |
| `iflytek-spark-text` | 讯飞星火 | 当前配置 |
| `minimax-text` | MiniMax 文本 | 当前配置 |
| `baichuan-text` | 百川 | 当前配置 |
| `stepfun-text` | 阶跃星辰 | 当前配置 |
| `sensenova-text` | 商汤日日新 | 当前配置 |
| `ai360-text` | 360 智脑 | 当前配置 |
| `mistral-text` | Mistral | 当前配置 |
| `xai-grok-text` | xAI Grok | 当前配置 |
| `openrouter-text` | OpenRouter | 当前配置 |
| `together-llama-text` | Together Llama | 当前配置 |
| `fireworks-llama-text` | Fireworks Llama | 当前配置 |
| `perplexity-sonar-text` | Perplexity Sonar | 当前配置 |
| `azure-openai-text` | Azure OpenAI | 当前配置 |
| `aws-bedrock-openai-compatible-text` | AWS Bedrock OpenAI Compatible | 当前配置 |
| `openai-responses-text` | OpenAI Responses | `gpt-5.5` |
| `mock-text` | Mock Text | Mock |
未启用:
- `openai-gpt54-text`
- `openai-gpt54-mini-text`
- `openai-gpt54-nano-text`
- `openai-gpt5-text`
- `openai-gpt41-text`
- `openai-gpt41-mini-text`
- `google-gemini-text`
- `anthropic-claude-text`
- `cohere-command-text`
### NovelProvider
已启用:
| Provider | 显示名 | 模型 |
| --- | --- | --- |
| `volcengine-doubao-seed20-pro-novel` | 豆包小说 2.0 Pro | `doubao-seed-2-0-pro-260215` |
| `volcengine-doubao-seed20-lite-novel` | 豆包小说 2.0 Lite | `doubao-seed-2-0-lite-260215` |
| `volcengine-doubao-novel` | 豆包小说 | `doubao-seed-1-6-250615` |
| `deepseek-novel` | DeepSeek 小说 | `deepseek-chat` |
| `qwen-novel` | 通义小说 | `qwen-plus` |
| `kimi-novel` | Kimi 小说 | `kimi-latest` |
| `zhipu-glm-novel` | 智谱小说 | `glm-4.5` |
| `openai-responses-novel` | OpenAI Responses 小说 | `gpt-5.5` |
| `mock-novel` | Mock Novel | Mock |
未启用:
- `openai-gpt54-novel`
- `openai-gpt54-mini-novel`
- `openai-gpt5-novel`
- `openai-gpt41-novel`
- `google-gemini-novel`
- `anthropic-claude-novel`
### ImageProvider
已启用:
| Provider | 显示名 | 模型 |
| --- | --- | --- |
| `volcengine-seedream-50-image` | 豆包 Seedream 5.0 图片 | `doubao-seedream-5-0-260128` |
| `volcengine-seedream-50-lite-image` | 豆包 Seedream 5.0 Lite 图片 | `doubao-seedream-5-0-lite-260128` |
| `volcengine-seedream-45-image` | 豆包 Seedream 4.5 图片 | `doubao-seedream-4-5-251128` |
| `openai-image` | OpenAI Image | `gpt-image-2` |
| `mock-image` | Mock Image | Mock |
未启用:
- `google-gemini-image`
- `stability-image`
- `replicate-flux-image`
- `fal-flux-image`
- `ideogram-image`
- `leonardo-image`
### VideoProvider
已启用:
| Provider | 显示名 | 模型 |
| --- | --- | --- |
| `volcengine_seedance_20_fast` | 豆包 Seedance 2.0 Fast 视频 | `doubao-seedance-2-0-fast-260128` |
| `volcengine_seedance_20` | 豆包 Seedance 2.0 视频 | `doubao-seedance-2-0-260128` |
| `jimeng_seedance` | 豆包 Seedance 1.5 Pro 视频 | `doubao-seedance-1-5-pro-251215` |
| `kling-image-to-video` | 可灵图生视频 | `kling-v3` |
| `kling-21-image-to-video` | 可灵 2.1 图生视频 | `kling-v2-1` |
| `kling-21-master-image-to-video` | 可灵 2.1 Master 图生视频 | `kling-v2-1-master` |
| `minimax_hailuo_23_fast` | 海螺 2.3 Fast | `MiniMax-Hailuo-2.3-Fast` |
| `minimax_hailuo_23` | 海螺 2.3 | `MiniMax-Hailuo-2.3` |
| `openai-video` | OpenAI Sora | `sora-2` |
| `mock-video` | Mock Video | Mock |
未启用:
- `alibaba_wan26_i2v_flash`
- `alibaba_wan26_i2v`
- `vidu_q3_turbo_reference`
- `vidu_q3_pro`
- `openai-sora-2-pro-video`
- `runway-image-to-video`
- `google-veo-video`
- `replicate-video`
- `fal-video`
- `luma-ray-video`
- `pika-video`
### VoiceProvider
已启用:
- `openai-tts``gpt-4o-mini-tts`
- `mock-voice`
未启用:
- `elevenlabs-tts`
- `minimax-tts`
- `volcengine-tts`
### LipSyncProvider
当前全部未启用:
- `mock-lipsync`
- `minimax-lipsync`
- `alibaba-videoretalk-lipsync`
- `heygen-lipsync`
- `sync-labs-lipsync`
- `fal-veed-lipsync`
- `volcengine-doubao-lipsync`
- `generic-lipsync`
### 其他 Provider
已启用:
- `openai-embedding`
- `mock-embedding`
- `mock-file-parse`
- `openai-moderation`
- `mock-moderation`
- `mock-quality-check`
## 5. Router 逻辑
Router 主要服务真人视频生成,核心文件:
- `backend/src/ai-router/ai-router.service.ts`
- `backend/src/ai-router/ai-router.types.ts`
默认配置:
- Router 版本:`ai.router.v1`
- 默认语言:`zh-CN`
- 每日预算:`500`
- 普通路线默认 Provider`minimax_hailuo_23_fast`
- 高价值路线默认 Provider`kling-image-to-video`
- 普通 fallback`minimax_hailuo_23_fast``volcengine_seedance_20_fast``volcengine_seedance_20``jimeng_seedance``mock-video`
- 高价值 fallback`kling-image-to-video``volcengine_seedance_20``minimax_hailuo_23_fast``volcengine_seedance_20_fast``jimeng_seedance``mock-video`
决策步骤:
1. 如果前端手动选择了视频模型,并且 Router 允许手动覆盖,优先使用手动 Provider。
2. 如果手动选择了模型,但系统不允许覆盖,直接返回错误,避免假装生效。
3. 没有手动选择时,读取系统 Router 配置。
4. 根据分镜文本推断 `scene_type`,例如对话、冲突、揭露、武打、玄幻变身等。
5. 对分镜打分:重要性、情绪强度、动作强度。
6. 如果重要性或动作强度较高,进入 `premium` 路线;否则进入 `normal` 路线。
7. 根据候选 Provider 顺序逐个检查:
- Provider 是否存在。
- Provider 是否启用。
- 单条成本是否超过上限。
- 当日预算是否超过限制。
- 时长、分辨率、比例等能力是否可用。
8. 选中第一个可用 Provider。
9. 记录 Router 决策、跳过原因、成本估算、Provider 调用日志。
当前实现特点:
- 支持前端手动指定 Provider。
- 支持按分镜打分自动调度。
- 支持 Provider fallback。
- 支持成本估算和日限额拦截。
- 支持 Provider 不可用时给出明确跳过原因。
- 支持长时长拆段,避免单个 Provider 不支持当前时长。
## 6. Prompt Builder 实现情况
核心文件:
- `backend/src/live-action/prompt-builder.service.ts`
- `backend/src/live-action/prompt-builder.service.spec.ts`
当前版本:
- `live-action-prompt-engine-v2`
Provider Profile
- `generic`
- `hailuo`
- `kling`
- `mock`
场景模板:
- `dialog`
- `conflict`
- `reveal`
- `engagement_breakup`
- `humiliation`
- `rich_arrival`
- `identity_reveal`
- `bank_balance_reveal`
- `boardroom_face_slap`
- `ceo_entrance`
- `dimensional_break`
- `xianxia_transformation`
- `action`
Prompt Builder 输出内容:
- prompt 版本。
- Provider profile。
- scene type。
- template ids。
- applied rules。
- route tier。
- aspect ratio。
- visual style。
- characters。
- actor consistency rules。
- location。
- main action。
- camera shot / camera move / camera tag。
- performance。
- lighting。
- VFX / sound cues。
- duration。
- continuity rules。
- motion director。
- director plan。
- lip sync policy。
- negative prompt。
不同 Provider 的处理:
- 海螺:偏中文真人短剧风格,控制提示词长度,强调镜头、人物、动作和短剧质感。
- 可灵:偏图生视频、参考图、动作连续性和真实镜头。
- 通用:偏 photorealistic vertical short drama。
- Mock:输出结构化 key-value,便于测试。
当前使用位置:
- 真人分镜准备后,视频片段生成前,会根据 Router 决策和 Provider Profile 重新构建最终提交给视频模型的 Prompt。
- `LiveActionService` 会把分镜、角色锁定信息、导演计划、唇形策略、Provider 能力一起传给 Prompt Builder。
待加强点:
- Prompt Builder 目前主要服务真人视频生成。
- 小说、故事圣经、角色抽取、分集、脚本、普通分镜等文本步骤虽然已有 Provider 接入点,但还需要统一成更严格的 schema、重试、验证和 Prompt 版本管理。
- 可继续增加“Prompt 调试面板”,把最终提交给 Provider 的完整参数、参考图、负面词、成本估算展示给前端测试人员。
## 7. Character Library 实现情况
核心文件:
- `backend/src/characters/characters.service.ts`
- `backend/src/characters/characters.controller.ts`
- `backend/src/characters/character.dto.ts`
- `backend/src/characters/character.types.ts`
- `backend/src/images/images.service.ts`
- `backend/src/live-action/live-action.service.ts`
当前角色体系分两层:
### 我的真人脸包
对应表:
- `GlobalCharacter`
- `GlobalCharacterAsset`
当前逻辑:
- 用户可以在“我的”里维护长期可复用的真人脸包。
- 真人脸包只保存脸部身份参考。
- 上传时需要本人/授权确认。
- 支持 1-10 张脸部参考图。
- 不默认把真人照当作项目角色锚点。
- 后续项目套用脸包时,需要在项目里生成或选择“仿真定妆锚点图”。
这样做的原因:
- 真人照片只用于锁脸,不应直接作为视频主角图。
- 不同项目有不同服装、发型、时代、风格,需要在项目内重新定妆。
- 视频模型对真人照片有限制时,可以把真人脸包作为身份参考,而不是首帧图。
### 项目角色库
对应表:
- `Character`
- `CharacterImage`
- `CharacterDesignVersion`
- `CharacterState`
- `ActorProfile`
当前逻辑:
- 项目可以从故事圣经、章节、提示词中抽取角色。
- 角色可以绑定我的真人脸包。
- 角色可以生成多张定妆图。
- 可设置角色锚点图。
- 可保存设计版本。
- 可保存状态变体,例如不同服装、受伤状态、战斗状态。
- `ActorProfile` 用于真人短剧阶段锁定角色参考图、锚点、脸包引用。
真人视频使用角色时:
1. 优先使用项目内已确认的定妆锚点图。
2. 真人脸包作为脸部参考。
3. 如果 Provider 支持角色参考图,则把参考图传入 Provider。
4. 如果 Provider 不支持角色参考图,则只在 Prompt 和前置关键帧生成里体现角色一致性。
5. 对不允许真人图直接生成视频的 Provider,会排除真人脸包作为首帧,避免触发真实人物限制。
## 8. FFmpeg 流程
相关文件:
- `backend/src/live-action/live-action.service.ts`
- `backend/src/media/media.service.ts`
- `backend/src/live-action/live-action.types.ts`
真人短剧 FFmpeg 合成流程:
```mermaid
flowchart TB
Selected[每个分镜已选择 VideoClip] --> Download[下载/读取素材文件]
Download --> Probe[ffprobe 探测\n时长 / 音轨 / 编码]
Probe --> Normalize[标准化片段\n裁剪 / 补齐 / 缩放 / pad / fps]
Normalize --> Concat[concat demuxer 拼接]
Concat --> VideoTrack[video-track.mp4]
VideoTrack --> Post[后期处理]
Dialogue[可选后期对白 / TTS] --> Post
BGM[可选 BGM] --> Post
SFX[可选音效] --> Post
Subtitle[可选 ASS 字幕] --> Post
Post --> Encode[编码输出\nlibx264 / libopenh264 / mpeg4 fallback]
Encode --> Final[最终 MP4]
```
标准化动作:
- 读取源视频。
- 按分镜时长裁剪或补齐。
- 统一为竖屏 `720x1280`
- `force_original_aspect_ratio=decrease` 后 pad。
- `setsar=1`
- `fps=30`
- `format=yuv420p`
- 根据配置决定是否保留源音频。
拼接动作:
- 每段生成临时标准化 clip。
- 写入 `clips.txt`
- 使用 FFmpeg concat demuxer 拼接。
- 输出 `video-track.mp4`
后期动作:
- 可选后期对白。
- 可选 BGM。
- 可选 SFX。
- 可选字幕。
- 可选画面 polish filter。
- 音频使用 `amix``loudnorm``limiter` 等策略混合。
编码器 fallback
1. 优先 `libx264`
2. 如果环境没有 `libx264`,使用 `libopenh264`
3. 如果仍不可用,退到 `mpeg4`
这解决了服务器 FFmpeg 缺少 `libx264` 时合成失败的问题。
当前后期策略:
- 合成时可命名成品,默认项目名。
- 分镜可以保留源视频声音。
- 后期对白、字幕、BGM、音效应由前端可选。
- 字幕不适合默认塞入长描述,当前应更偏短标题或分镜短句。
## 9. 当前已完成功能
### 基础工程
- NestJS 后端、Vue 前台、Vue 后台、BullMQ Worker 的 monorepo 结构。
- Prisma + MySQL 数据层。
- Redis 队列基础。
- StorageService 支持本地/对象存储/临时公网 URL。
- 全局 API 响应封装、异常处理、请求 ID。
### 用户与后台
- 用户登录、JWT、基础权限。
- 后台 Provider 管理。
- 后台用户、项目、素材、小说、运营配置管理。
- Provider 日志和成本记录。
### 小说系统
- 后台小说源管理。
- 小说简介、引文、章节管理。
- 章节增删改查。
- 批量粘贴导入。
- 支持按章节分隔符切割,例如 `===== 第6章:直播里的耳光 =====`
- 支持卷号逻辑,当前可按 30 章一卷。
- 前台小说列表、小说详情、目录、章节详情。
- 阅读进度保存。
- 书签。
- 批注。
- 搜索。
- 真书翻页模式和传统按钮模式的基础入口。
### 提示词直出分镜
- 可从外部提示词创建分镜项目。
- 支持解析 3 个镜头、不同镜头标题、不同镜头时长。
- 支持预览镜头数量和总时长。
- 创建后可进入真人分镜、关键帧、视频片段、合成流程。
- 可绑定我的真人脸包,但不会直接把真人照作为角色主图。
### AI Provider
- 文本、小说、图片、视频、语音、审核、向量、文件解析等 Provider 类型已建模。
- 支持启用/停用。
- 支持后台配置。
- 支持模型下拉按步骤类型过滤。
- 支持前端手动选模型。
- 支持默认智能计划。
- 支持 Provider 日志。
- 支持成本估算和日限额拦截。
### 真人短剧
- 角色抽取。
- 真人分镜准备。
- 文本模型可参与真人分镜改写。
- 角色锚点图生成。
- 关键帧生成。
- 单镜头测试生成。
- 批量视频片段生成。
- 多 Provider 生成候选片段。
- 每个分镜选择候选片段。
- 视频 Provider 预检。
- Provider 长任务轮询和恢复。
- 对超时但外部仍 running 的任务支持继续查询。
- 失败片段记录。
- 质量检查和人工审核入口。
- FFmpeg 合成真人短剧。
### 素材与作品
- 素材表记录图片、视频、音频、字幕、最终视频等。
- 视频片段记录 Provider、模型、成本、状态。
- 前台作品列表已区分视频/小说/素材方向。
- 图片和视频预览能力已具备基础形态。
## 10. 待优化功能
### Provider 能力矩阵
当前不同 Provider 的时长、分辨率、参考图能力不一致。需要继续把能力显式配置化:
- 支持时长:例如 4s、5s、6s、10s。
- 支持分辨率:例如 `720p``768P``1080P`
- 支持首帧。
- 支持尾帧。
- 支持角色参考图。
- 是否允许真人照片。
- 是否支持多参考图。
- 是否支持同步声音。
前端应根据能力矩阵隐藏不可用选项,而不是等 Provider 报错。
### 外部任务与费用
- 已有 RenderTask 和长任务恢复,但还可以增强“正在生成”Tab。
- 应支持取消、重新拉取、手动对账。
- 外部官方账单 API 尚未统一接入,当前成本主要来自本地估算和 ProviderLog。
- 需要按 Provider 建立实际账单同步策略。
### Prompt Builder
- 真人视频 Prompt Builder 已成型。
- 小说、故事圣经、角色抽取、分集、脚本、分镜等文本步骤需要统一 Prompt Builder、schema 校验和版本记录。
- 前台应展示最终提交参数,方便测试模型质量。
### Character Library
- 真人脸包和项目定妆已经拆开。
- 需要继续强化锚点图候选管理、选中状态、历史保留。
- 需要给用户明确说明上传脸包的照片要求。
- 需要支持“同一脸包在不同项目生成不同定妆”的对比管理。
### 真人/版权安全
- 视频模型可能拒绝真实人物图。
- 需要更清楚地区分本人授权、素材授权、商业可用状态。
- 需要生成记录可追溯到使用了哪个脸包、哪个锚点、哪个 Provider、哪个 Prompt。
### FFmpeg / 后期
- 服务器字体需要稳定打包,避免中文字幕显示方框。
- 字幕默认策略应更轻,只显示短标题或用户指定字幕。
- 后期对白需要按分镜时长自适应,避免裁剪和重叠。
- 源视频声音、后期配音、BGM、SFX 都应在前端合成前可选。
### 小说阅读器
- 真书翻页效果还可以继续做成点击右下角卷页,而不是按钮触发。
- 需要继续优化分页算法、阅读主题、字体、行距、自动保存。
- 可以增加章节购买/权限、阅读历史、多设备同步。
### 数据模型
- 当前大量关系通过 `*_id` 逻辑关联,没有全部声明 Prisma `@relation`
- 后续如果要生成更标准 ERD、级联删除、关联查询,可以逐步补充显式关系。
### 队列化
- 长耗时任务已有队列基础和部分恢复机制。
- 仍建议把图片生成、视频生成、合成、质量检查统一走 RenderTask + Worker,减少 HTTP 请求长时间等待。
## 11. 关键文件路径
### 工程入口
- `package.json`
- `backend/src/main.ts`
- `backend/src/app.module.ts`
- `backend/prisma/schema.prisma`
- `backend/prisma/seed.ts`
### Provider
- `backend/src/providers/providers.service.ts`
- `backend/src/providers/providers.controller.ts`
- `backend/src/providers/provider.types.ts`
- `backend/src/providers/providers.service.spec.ts`
- `backend/prisma/migrations/20260615143000_seedance_20_providers/`
- `backend/prisma/migrations/20260615152000_volcengine_creation_providers/`
- `backend/prisma/migrations/20260615165000_openai_model_pool/`
- `backend/prisma/migrations/20260615172000_volcengine_content_generation_video/`
- `backend/prisma/migrations/20260616014000_seedance_20_cost_rules/`
### Router
- `backend/src/ai-router/ai-router.service.ts`
- `backend/src/ai-router/ai-router.types.ts`
- `backend/src/ai-router/ai-router.service.spec.ts`
### Live Action
- `backend/src/live-action/live-action.service.ts`
- `backend/src/live-action/live-action.controller.ts`
- `backend/src/live-action/live-action.dto.ts`
- `backend/src/live-action/live-action.types.ts`
- `backend/src/live-action/prompt-builder.service.ts`
- `backend/src/live-action/prompt-builder.service.spec.ts`
- `backend/src/live-action/live-action-provider-acceptance.ts`
### Character / Image
- `backend/src/characters/characters.service.ts`
- `backend/src/characters/characters.controller.ts`
- `backend/src/characters/character.dto.ts`
- `backend/src/characters/character.types.ts`
- `backend/src/images/images.service.ts`
- `backend/src/images/images.controller.ts`
- `backend/src/images/image.dto.ts`
- `backend/src/images/image.types.ts`
- `backend/prisma/migrations/20260615125000_character_workshop_v1/`
### Project / Story / Script
- `backend/src/projects/projects.service.ts`
- `backend/src/projects/projects.controller.ts`
- `backend/src/projects/project.dto.ts`
- `backend/src/story-bibles/story-bibles.service.ts`
- `backend/src/story-bibles/story-bible.dto.ts`
- `backend/src/episodes/episodes.service.ts`
- `backend/src/episodes/episode.dto.ts`
- `backend/src/scripts/scripts.service.ts`
- `backend/src/scripts/script.dto.ts`
### Novel
- `backend/src/novels/novels.service.ts`
- `backend/src/novels/novels.service.spec.ts`
- `backend/src/novels/novel-parser.service.ts`
- `backend/src/novels/novel-parser.service.spec.ts`
- `backend/src/novels/novel.dto.ts`
- `backend/src/novels/novel.types.ts`
- `backend/src/novels/original-novel-mock.service.ts`
- `backend/src/novels/original-novel.dto.ts`
- `backend/src/novels/original-novel.types.ts`
- `backend/prisma/migrations/20260617093000_novel_chapter_volumes/`
- `backend/prisma/migrations/20260617111500_novel_reader_tools/`
### Media / FFmpeg
- `backend/src/media/media.service.ts`
- `backend/src/media/media.controller.ts`
- `backend/src/media/media.dto.ts`
- `backend/src/live-action/live-action.service.ts`
### Assets / Storage
- `backend/src/assets/assets.service.ts`
- `backend/src/assets/assets.controller.ts`
- `backend/src/assets/storage.service.ts`
- `backend/src/assets/public-temp-assets.controller.ts`
- `backend/src/assets/asset.types.ts`
### Queue / Worker
- `backend/src/queues/queues.service.ts`
- `backend/src/queues/worker-tasks.controller.ts`
- `workers/src/main.ts`
### Admin Frontend
- `admin/src/App.vue`
- `admin/src/api/client.ts`
- `admin/src/styles.css`
### User Frontend
- `user-app/src/pages/index/index.vue`
- `user-app/src/api/client.ts`
- `user-app/src/styles.css`
- `user-app/src/workflow.ts`
### Deploy / Tooling
- `deploy/nginx.https.example.conf`
- `deploy/docker-compose.dev.yml`
- `.env.example`
- `tools/frontend-visual-audit.mjs`
- `tools/frontend-business-e2e.mjs`
## 12. 当前 Router / Provider / Prompt / Character 的协作关系
```mermaid
flowchart TB
UI[前端步骤模型选择\n智能计划 / 手动模型] --> LiveAPI[LiveActionController]
LiveAPI --> LiveService[LiveActionService]
LiveService --> CharacterCtx[角色上下文\nCharacter / ActorProfile / FacePack / Anchor]
LiveService --> Router[AiRouterService]
Router --> ProviderConfig[ProviderConfig\n启用状态 / 成本 / 能力]
Router --> Decision[RouterDecision\nprovider / fallback / cost / tier]
CharacterCtx --> PromptBuilder[PromptBuilderService]
Decision --> PromptBuilder
PromptBuilder --> FinalPrompt[最终视频 Prompt\nPrompt Components / Negative Prompt]
FinalPrompt --> ProviderService[ProvidersService]
ProviderService --> ExternalAI[外部 AI 平台]
ExternalAI --> Asset[Asset / VideoClip / RenderTask]
```
关键原则:
- 前端每个 AI 步骤应只展示对应类型模型:文本、图片、视频、语音。
- 用户不选模型时走智能计划。
- 用户手动选模型时必须真实生效;如果不可用应直接报错。
- 同一分镜可以用多个视频模型生成多个候选。
- 合成前必须选择每个分镜最终使用哪个候选片段。
- 真人脸包只锁脸,项目锚点图才是视频角色主参考。
- Provider 报 running 时,本地不应直接判失败,应记录外部任务号并继续轮询恢复。