920 lines
31 KiB
Markdown
920 lines
31 KiB
Markdown
# 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 时,本地不应直接判失败,应记录外部任务号并继续轮询恢复。
|
||
|