Files
xiaoxia-saas/1197_preview_generation_proposal_v2.md
xiaoxia 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
feat: implement POST /assets/smart-match endpoint (#1242)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-08-05 09:51:01 +08:00

11 KiB
Executable File
Raw Permalink Blame History

#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 个 GenerationTaskis_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 需要对齐的接口

  1. 预览创建POST /templates/{id}/generate-preview
  2. 批次状态轮询GET /preview-batches/{id}(建议 2s 轮询,或走 SSE
  3. 预览转正式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 天)

  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 天(后端)