feat(#1677): 多视频批量生成后端补全 — 批量预览变体数组 + 按变体独立标题/配音/封面 #1701

Merged
auto-approve-bot merged 1 commits from feature/batch-variants-per-video-config into develop 2026-09-05 00:44:25 +08:00
Owner

多视频批量生成:后端能力补全(Issue #1677)

现状核实结论(与工单描述的出入)

工单中「后端已具备基础」部分,实际核实结果:

工单描述 实际情况
预览 API schema 已有 preview_count ⚠️ schema 有字段,但路由只创建 1 个任务,preview_count 是死参数(N 个预览靠前端 N 次并发调用凑)
预览 enqueue 前克隆独立变体 plan ⚠️ 单次请求只克隆 1 个 plan
clone_plan_for_variant() 变体克隆 本体完整(片段起点重算 + 受控复用 15% 闸门)
正式生成 count>1 自动克隆 plan(PR #1549) 完整
变体独立标题/配音/封面 整条链路都是整任务一份(title_config/voice_library_id/cover_url 单值)

本 PR 补全全部缺口。

变更内容

1. 批量预览 POST /api/v1/generation/preview

preview_count=N 时一次创建 N 个独立任务(不再需要前端 N 次并发调用):

  • N 个变体全部克隆独立 plan(预览不污染源 plan,避免 N 条预览片段相同)
  • 克隆在创建任务后、入队前批量完成,任一克隆失败 → 全部标记 failed + 500
  • 限流预检按变体总数计(pending + N)

2. 按变体独立配置(预览 + 正式生成两条链路)

新增数组字段,三个字段语义一致:空数组=回退旧单值字段;长度 1=所有变体共用;长度 N=按变体独立(其他长度 422):

字段 类型 说明
titles string[] 各变体标题文字(样式 font/color/position 仍走 title_config 全局共用)
voice_library_ids string[] 各变体配音素材库 ID
cover_urls string[] 各变体封面 URL(预览阶段通常不传)
  • N=1 且不传数组时行为与旧版完全一致(旧字段 voice_library_id/cover_url/title_config 全部保留有效)
  • 批量正式生成时 title_config 回写改为每个变体各自回写自己的克隆 plan(原逻辑仅首个任务回写一次)

接口数据结构(前端对接用)

批量预览请求 POST /api/v1/generation/preview

{
  "template_id": "tpl_xxx",
  "asset_ids": ["a1", "a2"],
  "preview_count": 3,                    // 1~10
  "title_config": { "font": "黑体", "font_color": "#FFFFFF", "position": "bottom" },  // 样式全局共用
  "titles": ["标题A", "标题B", "标题C"],  // 长度=preview_count 独立;长度1共用;不传用 title_config.text
  "voice_library_id": "voice_shared",   // 旧字段:共用配音
  "voice_library_ids": ["v1", "v2", "v3"], // 独立配音(传了优先于 voice_library_id)
  "video_ratio": "9:16",
  "bgm_config": {}
}

批量预览响应(结构变更:总是返回数组

{
  "items": [
    {
      "task_id": "t1", "variant_index": 0, "status": "pending", "progress": 0.0,
      "is_preview": true, "resolution": "1080x1920",
      "video_url": "",                  // 完成后有值
      "title_text": "标题A", "voice_library_id": "v1",
      "error_message": "", "duration": 0.0, "clip_count": 0,
      "created_at": "...", "finished_at": null
    },
    { "task_id": "t2", "variant_index": 1, ... },
    { "task_id": "t3", "variant_index": 2, ... }
  ],
  "total": 3
}

轮询方式不变:对每个 items[i].task_id 分别调 GET /api/v1/generation/preview/{task_id}(返回单个变体对象,结构同 items 元素)。

批量正式生成 POST /api/v1/generation/tasks

{
  "template_id": "tpl_xxx",
  "asset_ids": ["a1"],
  "count": 3,
  "source_edit_plan_id": "plan_xxx",    // 预览对应的 plan
  "title_config": { "font": "黑体" },   // 样式全局共用
  "titles": ["标题A", "标题B", "标题C"],
  "voice_library_ids": ["v1", "v2", "v3"],
  "cover_urls": ["https://.../c1.jpg", "https://.../c2.jpg", "https://.../c3.jpg"]
}

响应结构不变:{ items: [GenerationTaskResponse...], total: N },N 条独立成片。

确认生成 POST /tasks/{task_id}/confirm

不需要改动:批量场景前端对每个勾选的预览 task_id 分别调用 confirm(各自带 custom_title/cover_url),天然支持按变体独立。

测试

  • 新增 tests/unit/test_1677_batch_variants.py(24 个测试):数组长度校验、N=1/N=3 批量预览、克隆链路调用次数与 plan 关联、标题/配音按变体注入、共用模式、旧字段回退、克隆失败兜底
  • 更新 test_generation_preview.py 适配批量响应结构
  • 全量单测 14229 passed(5 个失败为已知 h2.config 环境问题,与本 PR 无关)
  • black/isort/ruff 全过

注意

  • GET /preview/{task_id} 单任务查询接口签名/返回不变,前端可直接复用
  • worker 无需改动:title_config/voice_library_id 均从 task 级别读取,变体隔离天然生效
# 多视频批量生成:后端能力补全(Issue #1677) ## 现状核实结论(与工单描述的出入) 工单中「后端已具备基础」部分,实际核实结果: | 工单描述 | 实际情况 | |---|---| | ✅ 预览 API schema 已有 `preview_count` | ⚠️ schema 有字段,但**路由只创建 1 个任务**,preview_count 是死参数(N 个预览靠前端 N 次并发调用凑) | | ✅ 预览 enqueue 前克隆独立变体 plan | ⚠️ 单次请求只克隆 1 个 plan | | ✅ `clone_plan_for_variant()` 变体克隆 | ✅ 本体完整(片段起点重算 + 受控复用 15% 闸门) | | ✅ 正式生成 count>1 自动克隆 plan(PR #1549) | ✅ 完整 | | 变体独立标题/配音/封面 | ❌ **整条链路都是整任务一份**(title_config/voice_library_id/cover_url 单值) | 本 PR 补全全部缺口。 ## 变更内容 ### 1. 批量预览 `POST /api/v1/generation/preview` **preview_count=N 时一次创建 N 个独立任务**(不再需要前端 N 次并发调用): - N 个变体**全部克隆独立 plan**(预览不污染源 plan,避免 N 条预览片段相同) - 克隆在创建任务后、入队前批量完成,任一克隆失败 → 全部标记 failed + 500 - 限流预检按变体总数计(pending + N) ### 2. 按变体独立配置(预览 + 正式生成两条链路) 新增数组字段,三个字段语义一致:**空数组=回退旧单值字段;长度 1=所有变体共用;长度 N=按变体独立**(其他长度 422): | 字段 | 类型 | 说明 | |---|---|---| | `titles` | `string[]` | 各变体标题文字(样式 font/color/position 仍走 `title_config` 全局共用) | | `voice_library_ids` | `string[]` | 各变体配音素材库 ID | | `cover_urls` | `string[]` | 各变体封面 URL(预览阶段通常不传) | - **N=1 且不传数组时行为与旧版完全一致**(旧字段 `voice_library_id`/`cover_url`/`title_config` 全部保留有效) - 批量正式生成时 `title_config` 回写改为**每个变体各自回写自己的克隆 plan**(原逻辑仅首个任务回写一次) ## 接口数据结构(前端对接用) ### 批量预览请求 `POST /api/v1/generation/preview` ```jsonc { "template_id": "tpl_xxx", "asset_ids": ["a1", "a2"], "preview_count": 3, // 1~10 "title_config": { "font": "黑体", "font_color": "#FFFFFF", "position": "bottom" }, // 样式全局共用 "titles": ["标题A", "标题B", "标题C"], // 长度=preview_count 独立;长度1共用;不传用 title_config.text "voice_library_id": "voice_shared", // 旧字段:共用配音 "voice_library_ids": ["v1", "v2", "v3"], // 独立配音(传了优先于 voice_library_id) "video_ratio": "9:16", "bgm_config": {} } ``` ### 批量预览响应(**结构变更:总是返回数组**) ```jsonc { "items": [ { "task_id": "t1", "variant_index": 0, "status": "pending", "progress": 0.0, "is_preview": true, "resolution": "1080x1920", "video_url": "", // 完成后有值 "title_text": "标题A", "voice_library_id": "v1", "error_message": "", "duration": 0.0, "clip_count": 0, "created_at": "...", "finished_at": null }, { "task_id": "t2", "variant_index": 1, ... }, { "task_id": "t3", "variant_index": 2, ... } ], "total": 3 } ``` **轮询方式不变**:对每个 `items[i].task_id` 分别调 `GET /api/v1/generation/preview/{task_id}`(返回单个变体对象,结构同 items 元素)。 ### 批量正式生成 `POST /api/v1/generation/tasks` ```jsonc { "template_id": "tpl_xxx", "asset_ids": ["a1"], "count": 3, "source_edit_plan_id": "plan_xxx", // 预览对应的 plan "title_config": { "font": "黑体" }, // 样式全局共用 "titles": ["标题A", "标题B", "标题C"], "voice_library_ids": ["v1", "v2", "v3"], "cover_urls": ["https://.../c1.jpg", "https://.../c2.jpg", "https://.../c3.jpg"] } ``` 响应结构不变:`{ items: [GenerationTaskResponse...], total: N }`,N 条独立成片。 ### 确认生成 `POST /tasks/{task_id}/confirm` **不需要改动**:批量场景前端对每个勾选的预览 task_id 分别调用 confirm(各自带 custom_title/cover_url),天然支持按变体独立。 ## 测试 - 新增 `tests/unit/test_1677_batch_variants.py`(24 个测试):数组长度校验、N=1/N=3 批量预览、克隆链路调用次数与 plan 关联、标题/配音按变体注入、共用模式、旧字段回退、克隆失败兜底 - 更新 `test_generation_preview.py` 适配批量响应结构 - 全量单测 14229 passed(5 个失败为已知 h2.config 环境问题,与本 PR 无关) - black/isort/ruff 全过 ## 注意 - `GET /preview/{task_id}` 单任务查询接口签名/返回不变,前端可直接复用 - worker 无需改动:title_config/voice_library_id 均从 task 级别读取,变体隔离天然生效
xiaoxia added 1 commit 2026-09-05 00:35:57 +08:00
feat(#1677): 多视频批量生成后端补全 — 批量预览变体数组 + 按变体独立标题/配音/封面
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m51s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m54s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m24s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 5m48s
AI Code Review / AI Code Review (pull_request) Successful in 6m19s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 7m36s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m22s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 9s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 41s
7a2748f6fd
- POST /preview: preview_count=N 一次创建 N 个独立预览任务(各自克隆独立 plan、
  独立 clips/随机起点),返回 {items: [...N变体], total},每个变体含独立
  task_id/status/video_url,前端按 task_id 分别轮询
- POST /tasks: count=N 时支持变体级配置注入:titles[]/voice_library_ids[]/
  cover_urls[](长度1=共用,长度N=独立,空数组=回退旧单值字段,N=1完全兼容)
- 标题样式(font/color/position 等)全局共用,标题文字按变体独立
- 批量场景 title_config 回写改为每个变体各自回写独立 plan(原仅首任务回写)
- 预览克隆链路:N 个预览全部克隆独立 plan(预览不污染源 plan),克隆失败中断
- 新增 BatchPreviewGenerationTaskResponse + PreviewGenerationTaskResponse
  增加 variant_index/title_text/voice_library_id 字段
- 24 个新单测覆盖 N=1/N=3 场景(变体数组校验/批量预览/克隆链路/独立配置注入)

🚀 预览环境已部署

项目 详情
PR号 #1701
预览链接 https://pr-1701.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1701 | | 预览链接 | [https://pr-1701.preview.xiaoxiajianji.com](https://pr-1701.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot merged commit c1763b995c into develop 2026-09-05 00:44:25 +08:00
auto-approve-bot deleted branch feature/batch-variants-per-video-config 2026-09-05 00:44:25 +08:00

🗑️ 预览环境已清理

PR #1701 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1701 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.