e27a48f0e0
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 1m16s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m38s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m44s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m17s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 3m29s
CI/CD Pipeline / Integration Tests (push) Successful in 1m40s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 6m29s
CI/CD Pipeline / Unit Tests (push) Successful in 8m8s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 14m13s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 47s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 47s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m8s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m59s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
383 lines
11 KiB
Markdown
Executable File
383 lines
11 KiB
Markdown
Executable File
# #1197 预览生成接口技术方案(v2)
|
||
|
||
> 更新说明:v2 新增「多版本预览生成」能力,支持一个模板生成多个不重复的预览视频,左侧列表展示,用户可挑选满意的版本转正式生成。
|
||
|
||
## 1. 背景与目标
|
||
|
||
**现状**:智能剪辑「一键生成」第3步预览生成被跳过,用户直接进入正式生成,缺少效果预览环节。
|
||
|
||
**目标**:
|
||
1. ✅ 实现真正的预览生成(低分辨率快速出片)
|
||
2. ✅ **支持生成 1~N 个不重复的预览版本**(默认 3 个),左侧列表展示
|
||
3. ✅ 预览满意后可一键转正式生成(复用素材下载缓存)
|
||
4. ✅ 不计入用户配额,不占用正式生成次数
|
||
|
||
---
|
||
|
||
## 2. 现有生成链路分析
|
||
|
||
### 2.1 链路总览
|
||
|
||
```
|
||
API 触发生成 → GenerationTask入库 → Celery异步任务
|
||
→ 下载素材 → 构建plan/clips → UnifiedRenderService渲染
|
||
→ 混音后处理 → OSS上传 + 查重 → 更新状态
|
||
```
|
||
|
||
### 2.2 决定视频差异的变量
|
||
|
||
要做"多个不重复版本",先分析哪些环节可以引入变化:
|
||
|
||
| 变量 | 当前行为 | 能否引入变化 | 影响程度 |
|
||
|------|---------|------------|---------|
|
||
| 素材选择 | 按 asset_ids 顺序全用 | ✅ 可随机选择子集/不同组合 | 大 |
|
||
| 素材排序 | 按 asset_ids 顺序 | ✅ 可 shuffle 重排 | 大 |
|
||
| 配音选择 | 固定 voice_library_id | ✅ 可选不同音色 | 中 |
|
||
| 标题选择 | 固定 title_ids 或随机选 | ✅ 可选不同标题 | 中 |
|
||
| BGM | 固定 bgm_config | ✅ 可选不同BGM | 小 |
|
||
| 转场效果 | 模板固定 | ✅ 可随机化转场类型 | 小 |
|
||
| 播放速度 | 模板固定 | ✅ 可微调速度 | 小 |
|
||
| 分辨率/码率 | 固定 | ✅ 预览可降级 | 不影响内容 |
|
||
|
||
### 2.3 可复用能力
|
||
|
||
- 任务创建与状态管理:`GenerationTask` + `CreateGenerationTaskUseCase`
|
||
- 素材下载与预处理:`_download_all_assets`
|
||
- 统一渲染引擎:`UnifiedRenderService`
|
||
- 分辨率配置:`resolution` 字段已支持
|
||
- 批量任务:`batch_id` 字段已存在(可用于预览组)
|
||
|
||
---
|
||
|
||
## 3. 总体方案:复用现有链路 + 多变体引擎
|
||
|
||
**核心思路**:沿用 v1 的"复用现有生成链路 + is_preview 标记"方案,在此基础上增加「多版本生成」能力。
|
||
|
||
**架构**:
|
||
```
|
||
预览生成请求(count=N)
|
||
↓
|
||
创建预览批次(preview_batch)
|
||
↓
|
||
变体引擎生成 N 个变体参数(variation seed + 参数组合)
|
||
↓
|
||
为每个变体创建 1 个 GenerationTask(is_preview=true)
|
||
↓
|
||
N 个 Celery 任务并行执行(走现有生成链路,参数降级)
|
||
↓
|
||
N 个结果汇聚,前端左侧列表展示
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 详细设计
|
||
|
||
### 4.1 数据模型变更
|
||
|
||
#### 4.1.1 GenerationTask 新增字段
|
||
|
||
```python
|
||
# 现有字段保留,新增:
|
||
is_preview: bool = False
|
||
"""是否为预览生成"""
|
||
|
||
preview_batch_id: str = ""
|
||
"""预览批次 ID(同批次的 N 个预览共享一个 batch)"""
|
||
|
||
variant_seed: int = 0
|
||
"""变体种子,用于控制随机化行为(素材选择、排序、转场等)"""
|
||
|
||
variant_params: dict = field(default_factory=dict)
|
||
"""变体参数快照(记录本次使用了哪些素材、标题、配音等,可追溯)
|
||
{
|
||
"asset_ids": [...], # 实际选用的素材子集
|
||
"title_id": "", # 选用的标题
|
||
"voice_id": "", # 选用的配音
|
||
"transition_style": "", # 转场风格
|
||
"bgm_track": "", # BGM 音轨
|
||
}
|
||
"""
|
||
```
|
||
|
||
#### 4.1.2 GeneratedVideo 新增字段
|
||
|
||
```python
|
||
is_preview: bool = False
|
||
"""是否为预览视频"""
|
||
|
||
preview_batch_id: str = ""
|
||
"""所属预览批次"""
|
||
|
||
variant_index: int = 0
|
||
"""在批次中的序号(0, 1, 2...)"""
|
||
```
|
||
|
||
#### 4.1.3 迁移方案
|
||
|
||
alembic 新增 migration,两个表各加 4 个字段,默认值为空/false,无数据回填成本。
|
||
|
||
---
|
||
|
||
### 4.2 变体引擎(Variant Engine)
|
||
|
||
**核心组件**:根据 count 和 seed,生成 N 组互不相同的生成参数。
|
||
|
||
#### 4.2.1 变纬度设计
|
||
|
||
| 维度 | 策略 | 说明 |
|
||
|------|------|------|
|
||
| **素材子集选择** | 从素材池中随机选 M 个(M=min(素材数, 模板clip数*2)) | 版本差异最大的来源 |
|
||
| **素材排序** | 随机打乱顺序 | 影响叙事节奏 |
|
||
| **标题选择** | 从 title_ids 中随机选 1 个 | 影响文案内容 |
|
||
| **配音选择** | 从 voice_ids 中随机选 1 个(如有多个) | 影响听觉体验 |
|
||
| **转场风格** | 从预设转场池中随机选 1 种 | 影响视觉过渡 |
|
||
| **BGM 选择** | 从 bgm 列表中随机选 1 首(如有配置) | 影响氛围 |
|
||
|
||
#### 4.2.2 去重机制
|
||
|
||
- 同一批次内,变体参数必须两两不同(至少素材组合或排序不同)
|
||
- 使用 `variant_seed` 保证可复现(相同 seed → 相同变体)
|
||
- 如果素材数量不足导致无法生成 N 个不同版本,按实际能生成的数量返回
|
||
|
||
#### 4.2.3 接口设计
|
||
|
||
```python
|
||
def generate_variants(
|
||
count: int,
|
||
seed: int,
|
||
asset_pool: list[str], # 可用素材 ID 列表
|
||
title_pool: list[str] = [], # 可用标题 ID 列表
|
||
voice_pool: list[str] = [], # 可用配音 ID 列表
|
||
template_id: str = "",
|
||
) -> list[dict]:
|
||
"""
|
||
生成 count 组变体参数。
|
||
|
||
每组参数包含:asset_ids(选用的素材+排序)、title_id、voice_id、
|
||
transition_style 等,确保两两不同。
|
||
"""
|
||
```
|
||
|
||
---
|
||
|
||
### 4.3 API 层设计
|
||
|
||
#### 4.3.1 预览生成接口
|
||
|
||
```
|
||
POST /api/v1/templates/{template_id}/generate-preview
|
||
```
|
||
|
||
**请求体**:
|
||
```json
|
||
{
|
||
"asset_library_id": "lib_xxx",
|
||
"asset_ids": ["asset_1", "asset_2", ...],
|
||
"title_ids": ["title_1", "title_2"],
|
||
"voice_ids": ["voice_1", "voice_2"],
|
||
"bgm_config": {},
|
||
"count": 3,
|
||
"seed": 0
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||
|------|------|------|------|------|
|
||
| template_id | path | ✅ | - | 模板 ID |
|
||
| asset_library_id | body | ✅ | - | 素材库 ID |
|
||
| asset_ids | body | ✅ | - | 素材池(从中选子集/排序) |
|
||
| title_ids | body | - | [] | 标题池(可选,不传则不用标题) |
|
||
| voice_ids | body | - | [] | 配音池(可选) |
|
||
| bgm_config | body | - | {} | BGM 配置 |
|
||
| count | body | - | 3 | 生成几个预览版本(1~10) |
|
||
| seed | body | - | 0 | 随机种子,0 表示随机 |
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"preview_batch_id": "pb_xxx",
|
||
"count": 3,
|
||
"tasks": [
|
||
{
|
||
"task_id": "gen_xxx_0",
|
||
"variant_index": 0,
|
||
"status": "processing"
|
||
},
|
||
{
|
||
"task_id": "gen_xxx_1",
|
||
"variant_index": 1,
|
||
"status": "processing"
|
||
},
|
||
...
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 4.3.2 预览批次查询接口
|
||
|
||
```
|
||
GET /api/v1/preview-batches/{batch_id}
|
||
```
|
||
|
||
返回批次内所有预览任务的状态、结果(已完成的带 video_url)。
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"preview_batch_id": "pb_xxx",
|
||
"count": 3,
|
||
"completed_count": 2,
|
||
"tasks": [
|
||
{
|
||
"task_id": "gen_xxx_0",
|
||
"variant_index": 0,
|
||
"status": "completed",
|
||
"video_url": "https://oss.xxx/preview/xxx.mp4",
|
||
"duration": 15.5,
|
||
"thumbnail_url": "https://oss.xxx/preview/xxx.jpg"
|
||
},
|
||
...
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 4.3.3 预览转正式生成
|
||
|
||
```
|
||
POST /api/v1/preview-batches/{batch_id}/tasks/{task_id}/promote
|
||
```
|
||
|
||
将某个预览版本升级为正式生成(复用素材缓存,重新全分辨率渲染)。
|
||
|
||
---
|
||
|
||
### 4.4 渲染参数降级
|
||
|
||
预览模式下自动调整以下参数:
|
||
|
||
| 参数 | 正式生成 | 预览生成 |
|
||
|------|---------|---------|
|
||
| 分辨率 | 720p (1280x720) | 480p (854x480) |
|
||
| 码率 | 4 Mbps | 1.5 Mbps |
|
||
| 帧率 | 30 fps | 24 fps |
|
||
| 时长 | 完整时长 | 前 15 秒(或第一段完整clip) |
|
||
| 转场效果 | 完整转场 | 仅淡入淡出 |
|
||
| 高级特效 | 全部启用 | 跳过粒子/光效等 |
|
||
| 字幕 | 完整渲染 | 正常渲染 |
|
||
| 配音 | 完整混音 | 正常混音 |
|
||
| 输出质量 | high | medium |
|
||
|
||
**实现位置**:`_render_video` 函数入口处,根据 `is_preview` 标记调整渲染配置。
|
||
|
||
---
|
||
|
||
### 4.5 任务调度
|
||
|
||
- **并行执行**:N 个预览任务并行提交到 Celery,不排队等待
|
||
- **低优先级**:预览任务走独立队列(`preview_queue`),不抢占正式生成资源
|
||
- **超时控制**:预览任务超时时间 5 分钟(正式 30 分钟)
|
||
- **自动清理**:预览视频 7 天后自动从 OSS 删除,任务记录标记为 archived
|
||
|
||
---
|
||
|
||
## 5. 前端对接要点
|
||
|
||
### 5.1 交互流程
|
||
|
||
```
|
||
第2步选素材 → 第3步点击"生成预览"
|
||
→ 显示 loading + 进度
|
||
→ 预览陆续完成,左侧列表逐张出现
|
||
→ 用户点击左侧不同版本,右侧预览区切换
|
||
→ 用户选中满意版本 → 点击"正式生成"
|
||
```
|
||
|
||
### 5.2 需要对齐的接口
|
||
|
||
1. **预览创建**:`POST /templates/{id}/generate-preview`
|
||
2. **批次状态轮询**:`GET /preview-batches/{id}`(建议 2s 轮询,或走 SSE)
|
||
3. **预览转正式**:`POST /preview-batches/{id}/tasks/{task_id}/promote`
|
||
|
||
### 5.3 数据格式对齐
|
||
|
||
预览视频条目结构:
|
||
```json
|
||
{
|
||
"id": "gen_xxx",
|
||
"variant_index": 0,
|
||
"status": "completed",
|
||
"video_url": "https://...",
|
||
"duration": 15.5,
|
||
"file_size": 2850000,
|
||
"thumbnail_url": "https://...",
|
||
"is_preview": true
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 配额与计费
|
||
|
||
- 预览生成**不计入**用户配额
|
||
- 同一模板 + 同一素材池,每天最多生成 3 次多版本预览(防滥用)
|
||
- 单个预览批次最多 10 个版本
|
||
|
||
---
|
||
|
||
## 7. 实施步骤
|
||
|
||
### Phase 1:单版本预览(MVP,2 天)
|
||
1. 数据模型 + 迁移(is_preview 字段)
|
||
2. API 层支持 is_preview 参数
|
||
3. 渲染分辨率降级(480p)
|
||
4. 不计入配额
|
||
5. 基础测试
|
||
|
||
### Phase 2:多版本预览(3 天)
|
||
1. 变体引擎实现(素材随机选择 + 排序 + 去重)
|
||
2. preview_batch 批次管理
|
||
3. 批量创建 N 个预览任务
|
||
4. 批次查询接口
|
||
5. 前端联调
|
||
|
||
### Phase 3:预览转正式 + 优化(2 天)
|
||
1. 预览转正式生成接口(promote)
|
||
2. 素材下载缓存复用
|
||
3. 独立预览队列(低优先级)
|
||
4. 自动清理机制
|
||
5. 完整测试 + 压测
|
||
|
||
---
|
||
|
||
## 8. 风险与注意事项
|
||
|
||
| 风险 | 影响 | 应对 |
|
||
|------|------|------|
|
||
| 并发预览任务过多打满 worker | 正式生成被阻塞 | 独立预览队列 + 限流 |
|
||
| 变体生成的视频差异不够大 | 用户觉得"都一样" | 优先素材子集+排序差异,保证视觉差异 |
|
||
| 预览视频占用 OSS 存储 | 存储成本上升 | 7 天自动清理 + 低码率 |
|
||
| N 个版本同时下载重复素材 | 带宽浪费 | 批次内共享一次下载(Phase 3 优化) |
|
||
| 用户预期管理 | 以为预览就是最终效果 | 明确标注"预览版",说明分辨率差异 |
|
||
|
||
---
|
||
|
||
## 9. 开发量估算
|
||
|
||
| 阶段 | 后端 | 前端 | 合计 |
|
||
|------|------|------|------|
|
||
| Phase 1 单版本预览 | 2 天 | 1 天 | 3 天 |
|
||
| Phase 2 多版本预览 | 3 天 | 2 天 | 5 天 |
|
||
| Phase 3 转正式+优化 | 2 天 | 1 天 | 3 天 |
|
||
| **总计** | **7 天** | **4 天** | **~7 天(并行)** |
|
||
|
||
---
|
||
|
||
## 10. 与 v1 方案的差异总结
|
||
|
||
1. **新增多版本能力**:从"生成1个预览"升级为"生成N个不重复预览"
|
||
2. **新增变体引擎**:负责素材选择/排序/配音/标题的随机化
|
||
3. **新增批次概念**:preview_batch 管理一组预览任务
|
||
4. **新增 promote 接口**:预览转正式生成
|
||
5. **独立队列**:预览不抢占正式生成资源
|
||
6. **开发量**:从 2-3 天增加到约 7 天(后端)
|