16 KiB
场景多候选功能规格文档
ADDED Requirements
Requirement: 场景候选数据结构
MUST: 每个场景必须支持存储多个候选视频素材,替代原有的单一素材模式。 优先级: 高 版本: v1.0
数据结构:
interface Scene {
index: number; // 场景序号
candidates: Material[]; // 候选素材列表
duration: number; // 单场景时长
}
interface Material {
fileId: number; // 素材文件ID
fileUrl: string; // 素材文件URL
fileDuration?: number; // 素材实际时长(可选)
}
验证规则:
- 每个场景至少包含 1 个候选素材
- 每个场景最多包含 10 个候选素材
- 同一场景内的候选素材不能重复(基于 fileId 判断)
- 候选素材必须为视频类型
Scenario: 创建新场景
用户调整总时长和单切片时长后,系统自动创建对应数量的空场景。每个场景初始化时包含一个空的候选列表,等待用户添加素材。
Scenario: 添加候选
用户点击场景格子,打开候选选择弹窗,从素材库中选择多个视频素材添加到场景的候选列表中。
Scenario: 验证重复
当用户尝试添加已在候选列表中的素材时,系统自动检查并阻止添加,同时在UI上显示提示信息。
Scenario: 限制数量
当场景的候选数量达到上限(10个)时,系统禁用添加按钮,并提示用户已达到最大候选数量。
Requirement: 场景候选管理操作
MUST: 用户必须能够对场景的候选素材进行增删改查操作。
操作类型:
- 添加候选:从素材库选择视频添加到场景候选
- 移除候选:从场景候选中移除指定的素材
- 清空场景:移除场景的所有候选素材
- 查看候选:以弹窗或侧边栏形式展示所有候选
交互规则:
- 点击场景格子打开候选选择弹窗
- 弹窗中显示当前场景已选候选数量
- 素材库中已选候选显示"已选择"状态
- 支持批量选择多个候选后一次性确认
Scenario: 添加单个候选
用户在场景格子上的弹窗中选择一个素材,确认后该素材被添加到场景的候选列表中。
Scenario: 批量添加候选
用户在素材库中选择多个素材,然后点击"批量添加"按钮,一次性将所有选中的素材添加到场景候选列表中。
Scenario: 移除候选
用户在场景格子或弹窗中点击候选素材上的移除按钮,系统将该候选从场景候选列表中删除。
Scenario: 查看候选详情
用户点击场景格子,系统以弹窗形式展示该场景的所有候选素材,包括缩略图、文件名和时长信息。
Requirement: 一键填充功能优化
MUST: 系统必须优化一键填充功能,自动为每个场景添加多个候选素材。
填充策略:
- 随机分配:从素材库中随机选择素材分配给每个场景
- 防重复:确保同一场景内的候选不重复
- 尽量均匀:尽可能平均分配素材到各个场景
- 数量控制:每个场景填充 3-5 个候选(根据素材库数量动态调整)
算法逻辑:
For each scene in scenes:
If scene.candidates.isEmpty():
randomly select 3-5 materials from groupFiles
ensure no duplicate within scene
add to scene.candidates
Scenario: 自动填充空场景
用户点击"一键填充"按钮,系统只填充空的场景,已有候选的场景保持不变。
Scenario: 补充候选数量
如果场景的候选数量不足默认数量(3个),系统自动补充候选素材到默认数量。
Scenario: 全量填充
用户选择"全量填充"选项,系统为所有场景(包括已有候选的场景)重新填充候选素材。
Scenario: 智能跳过
系统自动检测已填满的场景并跳过,只处理需要填充的场景。
Requirement: 场景候选可视化展示
MUST: 系统必须在前端界面中清晰展示每个场景的候选数量和候选列表。
UI 展示元素:
- 候选数量标签:在场景格子上显示"候选数量/X"
- 候选列表预览:以缩略图或标签形式展示候选
- 使用状态标识:标识哪些候选已被使用
- 悬停提示:鼠标悬停显示候选详细信息
样式规范:
- 候选数量使用徽标组件(badge)展示
- 候选列表使用小缩略图或文件图标
- 已使用候选使用不同颜色或图标标识
- 悬停提示显示候选文件名和时长
Scenario: 查看候选概览
用户在主界面上可以直观地看到每个场景显示的候选数量,快速了解整体配置情况。
Scenario: 预览候选内容
用户将鼠标悬停在场景格子上,系统显示该场景所有候选的缩略图预览。
Scenario: 识别使用状态
用户可以通过不同的视觉标识(如颜色、图标)快速识别哪些候选素材已被使用。
Scenario: 快速定位
用户通过可视化展示快速定位需要编辑的场景,提高操作效率。
Requirement: 场景候选防重复机制
MUST: 系统必须确保同一场景内的候选素材不重复,保证素材多样性。
验证机制:
- 前端验证:在选择素材时实时检查并提示
- 后端验证:在提交时进行最终验证
- UI 反馈:已选择的素材显示禁用或选中状态
重复判断规则:
- 基于
fileId进行唯一性判断 fileId相同视为重复素材- 允许同一素材在不同场景中出现
Scenario: 阻止重复添加
用户在选择素材时,如果该素材已在候选列表中,系统立即提示"该素材已在候选列表中",并阻止添加。
Scenario: 视觉反馈
已选择的素材在素材库中显示为禁用状态,用户可以直观地看到哪些素材已被选择。
Scenario: 批量去重
一键填充功能自动去除重复候选,确保每个场景内的候选都是唯一的。
Scenario: 手动去重
用户可以在场景候选列表中手动移除重复的候选素材,系统保持列表的唯一性。
MODIFIED Requirements
Requirement: 混剪任务提交数据结构
MUST: 系统必须修改混剪任务提交数据结构以支持场景多候选模式。
修改前: MUST: ```json { "title": "视频标题", "materials": [ {"fileId": 1, "fileUrl": "url1", "duration": 3}, {"fileId": 2, "fileUrl": "url2", "duration": 3} ], "produceCount": 3 }
**系统必须修改为以下结构:**
```json
{
"title": "视频标题",
"scenes": [
{
"duration": 3,
"candidates": [
{"fileId": 1, "fileUrl": "url1", "fileDuration": 60},
{"fileId": 2, "fileUrl": "url2", "fileDuration": 45}
]
},
{
"duration": 3,
"candidates": [
{"fileId": 3, "fileUrl": "url3", "fileDuration": 50},
{"fileId": 4, "fileUrl": "url4", "fileDuration": 55}
]
}
],
"produceCount": 3
}
向后兼容:
- 支持旧的
materials字段格式 - 当接收到
materials时,自动转换为新的scenes格式 - 保持现有 API 端点不变
Scenario: 提交新格式
前端使用新的 scenes 格式提交混剪任务,包含每个场景的候选素材列表。
Scenario: 兼容旧格式
后端接收到包含 materials 字段的旧格式数据时,自动将其转换为 scenes 格式(每个场景包含一个候选)。
Scenario: 数据转换
系统将旧格式的 materials 数组转换为新格式的 scenes 数组,每个场景包含一个候选素材。
Scenario: 版本协商
前后端协商确定使用的数据格式,优先使用新格式,向后兼容旧格式。
Requirement: 批量混剪随机选择逻辑
MUST: 系统必须实现两层随机选择逻辑以最大化视频内容差异。
修改前: MUST: 使用相同的素材列表,通过随机起点实现差异化:
// 每个视频使用相同的素材,不同的截取起点
List<MaterialItem> materials = createReqVO.getMaterials();
for (int videoIndex = 0; videoIndex < produceCount; videoIndex++) {
produceSingleVideoWithOffset(materials, videoIndex, userId, cropMode);
}
系统必须修改为以下结构: 系统必须从每个场景的候选中随机选择一个素材,然后仍然使用随机起点:
// 从每个场景的候选中随机选择素材,然后通过随机起点实现差异化
List<SceneConfig> scenes = createReqVO.getScenes();
for (int videoIndex = 0; videoIndex < produceCount; videoIndex++) {
List<MaterialItem> selectedMaterials = new ArrayList<>();
for (SceneConfig scene : scenes) {
// 从场景的候选中随机选择一个素材
MaterialItem selected = selectRandomCandidate(scene.getCandidates(), videoIndex, scene.getIndex());
selectedMaterials.add(selected);
}
// 对选中的素材使用随机起点生成视频
produceSingleVideoWithOffset(selectedMaterials, videoIndex, userId, cropMode);
}
随机选择算法:
- 第一层随机:基于
videoIndex、sceneIndex和候选素材fileId从每个场景的候选中随机选择一个素材 - 第二层随机:对选中的素材仍然使用随机起点实现进一步差异化
- 确保同一
videoIndex在不同时间运行结果一致 - 保证不同
videoIndex选择的素材不同(尽可能)
示例:
- 场景1有候选[A, B, C],场景2有候选[D, E, F],场景3有候选[G, H, I]
- 视频1:可能选择 A + D + G,然后从A的随机起点1、B的随机起点2...生成
- 视频2:可能选择 B + E + H,然后从B的随机起点2、E的随机起点3...生成
- 视频3:可能选择 C + F + I,然后从C的随机起点3、F的随机起点1...生成
Scenario: 生成第一个视频
从每个场景的候选中使用第一层随机选择一个素材,然后对每个素材应用随机起点生成视频。
Scenario: 生成第二个视频
从每个场景的候选中再次随机选择(尽量与第一个视频不同),然后应用不同的随机起点。
Scenario: 生成第N个视频
每个视频都经历两层随机选择:第一层从场景候选中选择,第二层对选中素材应用随机起点。
Scenario: 保证差异化
通过两层随机性(候选选择 + 随机起点),最大化每个生成视频的内容差异。
Requirement: 场景配置验证规则
MUST: 系统必须更新场景配置验证规则以支持多候选场景。
修改前: MUST: 验证素材列表:
// 验证素材列表不为空
if (req.getMaterials() == null || req.getMaterials().isEmpty()) {
throw new IllegalArgumentException("素材列表不能为空");
}
// 验证总时长
int totalDuration = req.getMaterials().stream()
.mapToInt(MixTaskSaveReqVO.MaterialItem::getDuration)
.sum();
系统必须修改为以下结构: 系统必须验证场景配置:
// 验证场景列表不为空
if (req.getScenes() == null || req.getScenes().isEmpty()) {
throw new IllegalArgumentException("场景列表不能为空");
}
// 验证每个场景至少有一个候选
for (SceneConfig scene : req.getScenes()) {
if (scene.getCandidates() == null || scene.getCandidates().isEmpty()) {
throw new IllegalArgumentException("场景" + scene.getIndex() + "没有候选素材");
}
if (scene.getCandidates().size() > MAX_CANDIDATES_PER_SCENE) {
throw new IllegalArgumentException("场景候选数量不能超过" + MAX_CANDIDATES_PER_SCENE);
}
}
// 验证总时长
int totalDuration = req.getScenes().stream()
.mapToInt(scene -> scene.getDuration() * scene.getCandidates().size())
.sum();
Scenario: 验证场景完整性
检查所有场景都必须包含至少一个候选素材,缺少候选的场景抛出异常。
Scenario: 验证候选数量
检查每个场景的候选数量在允许范围内(1-10个),超过上限抛出异常。
Scenario: 验证总时长
根据场景数量和候选数量计算总时长,验证是否在 15-30 秒范围内。
Scenario: 验证素材有效性
检查所有候选素材的文件ID和URL有效性,无效素材导致验证失败。
性能要求
Requirement: 场景加载性能
目标: 场景数据加载时间 < 2 秒 测量: 从用户选择素材分组到场景渲染完成的时间 场景: 50 个候选素材,5 个场景
Scenario: 正常加载
MUST: 在50个候选素材、5个场景的情况下,场景数据加载时间不超过2秒。
Scenario: 大量素材加载
测试100个候选素材、10个场景的加载性能,确保仍在可接受范围内。
Scenario: 网络延迟场景
在网络延迟300ms的情况下,场景加载时间仍在用户可接受范围内。
Scenario: 缓存优化
利用前端缓存机制,提升重复访问时的场景加载速度。
Requirement: 批量混剪性能
目标: 混剪任务创建时间与现有实现持平(< 3 秒) 测量: 从用户点击"开始混剪"到任务创建成功的时间 场景: 5 个场景,每个场景 3-5 个候选,生成 5 个视频
Scenario: 标准场景混剪
MUST: 在标准配置下(5个场景,每个场景3-5个候选),混剪任务创建时间不超过3秒。
Scenario: 大量候选混剪
测试每个场景10个候选的极限情况,性能仍在可接受范围内。
Scenario: 批量生成性能
生成5个视频的批量混剪性能与现有实现持平。
Scenario: 并发场景
测试多个用户同时创建混剪任务的性能表现。
Requirement: 内存使用
目标: 前端内存使用增长 < 20% 测量: 场景候选功能开启前后的内存使用对比 场景: 长时间使用混剪功能,累积创建多个任务
Scenario: 正常使用内存
MUST: 用户正常操作混剪功能,内存使用增长不超过20%。
Scenario: 长时间使用
用户连续使用混剪功能1小时,内存无明显泄漏。
Scenario: 大量数据处理
处理大量候选素材时,内存使用保持在合理范围内。
Scenario: 内存回收
页面切换或刷新后,前端内存能够正确释放。
兼容性要求
Requirement: 向后兼容
要求: 支持现有的 materials 格式
实现: 自动转换旧格式为新格式
测试: 使用旧格式创建混剪任务
Scenario: 旧格式请求
MUST: 后端接收到包含materials字段的请求时,自动转换为scenes格式。
Scenario: 新格式请求
前端优先使用新的scenes格式提交请求。
Scenario: 格式检测
系统能够自动检测请求使用的格式并进行相应处理。
Scenario: 错误处理
当格式转换失败时,提供清晰的错误信息。
Requirement: 渐进式迁移
要求: 用户可以选择使用新模式或旧模式 实现: 通过功能开关控制 场景: 新用户使用新模式,老用户可以选择继续使用旧模式
Scenario: 功能开关
MUST: 提供开关让用户选择使用新模式或旧模式。
Scenario: 用户偏好保存
用户的选择偏好能够持久化保存,下次访问时保持上次选择。
Scenario: 模式切换
用户可以在新旧模式之间自由切换。
Scenario: 默认模式
新用户默认使用新模式,老用户默认使用旧模式。
安全要求
Requirement: 输入验证
要求: 严格验证所有用户输入 范围: 文件ID、URL、候选数量等 场景: 防止恶意用户提交非法数据
Scenario: 文件ID验证
MUST: 验证所有文件ID必须是有效的数字,且对应的文件存在。
Scenario: URL验证
验证所有URL必须是有效的OSS地址,防止XSS攻击。
Scenario: 候选数量限制
限制候选数量在合理范围内,防止DDoS攻击。
Scenario: SQL注入防护
使用参数化查询,防止SQL注入攻击。
Requirement: 权限控制
要求: 候选素材必须属于当前用户或有权限访问 实现: 后端验证素材所有权 场景: 用户尝试添加他人素材到候选列表
Scenario: 素材所有权验证
MUST: 后端验证候选素材是否属于当前用户或用户有权限访问。
Scenario: 权限检查
对每个候选素材进行权限检查,无权限的素材拒绝添加。
Scenario: 越权防护
防止用户访问或操作其他用户的素材。
Scenario: 审计日志
记录所有素材访问和操作日志,便于安全审计。