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>
11 KiB
Executable File
11 KiB
Executable File
#1197 预览生成接口技术方案(v2)
更新说明:v2 新增「多版本预览生成」能力,支持一个模板生成多个不重复的预览视频,左侧列表展示,用户可挑选满意的版本转正式生成。
1. 背景与目标
现状:智能剪辑「一键生成」第3步预览生成被跳过,用户直接进入正式生成,缺少效果预览环节。
目标:
- ✅ 实现真正的预览生成(低分辨率快速出片)
- ✅ 支持生成 1~N 个不重复的预览版本(默认 3 个),左侧列表展示
- ✅ 预览满意后可一键转正式生成(复用素材下载缓存)
- ✅ 不计入用户配额,不占用正式生成次数
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 新增字段
# 现有字段保留,新增:
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 新增字段
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 接口设计
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
请求体:
{
"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 表示随机 |
响应:
{
"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)。
响应:
{
"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 需要对齐的接口
- 预览创建:
POST /templates/{id}/generate-preview - 批次状态轮询:
GET /preview-batches/{id}(建议 2s 轮询,或走 SSE) - 预览转正式:
POST /preview-batches/{id}/tasks/{task_id}/promote
5.3 数据格式对齐
预览视频条目结构:
{
"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 天)
- 数据模型 + 迁移(is_preview 字段)
- API 层支持 is_preview 参数
- 渲染分辨率降级(480p)
- 不计入配额
- 基础测试
Phase 2:多版本预览(3 天)
- 变体引擎实现(素材随机选择 + 排序 + 去重)
- preview_batch 批次管理
- 批量创建 N 个预览任务
- 批次查询接口
- 前端联调
Phase 3:预览转正式 + 优化(2 天)
- 预览转正式生成接口(promote)
- 素材下载缓存复用
- 独立预览队列(低优先级)
- 自动清理机制
- 完整测试 + 压测
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个预览"升级为"生成N个不重复预览"
- 新增变体引擎:负责素材选择/排序/配音/标题的随机化
- 新增批次概念:preview_batch 管理一组预览任务
- 新增 promote 接口:预览转正式生成
- 独立队列:预览不抢占正式生成资源
- 开发量:从 2-3 天增加到约 7 天(后端)