# 混剪场景编排功能重新设计提案 ## 变更概述 **变更ID:** refactor-mix-scene编排 **日期:** 2025-12-21 **优先级:** 高 ## Why (为什么需要这个变更) 当前混剪功能的单一场景模式导致批量生成视频时内容高度相似,无法满足用户对视频多样性的需求。通过引入多候选场景模式,用户可以为每个场景准备多个候选素材,系统在批量混剪时从每个场景的候选中随机选择,从而生成内容差异显著的多个视频。这将显著提升用户体验,满足内容创作者对多样性的追求。 ## 问题背景 当前的混剪场景编排功能存在以下限制: 1. **场景素材单一性**:每个场景只能选择一个视频素材,导致批量混剪时视频内容相似度极高 2. **多样性不足**:虽然后端通过随机起点实现差异化,但本质上仍使用相同的素材池 3. **用户需求未满足**:用户希望一次混剪能生成内容差异更大的多个视频 ## 解决方案 ### 核心设计理念 重新设计场景编排为**"多候选场景模式"**: - 每个场景包含**多个候选视频**(每个场景内视频不重复) - 批量混剪时,**从每个场景的候选中随机选择一个**视频 - 仍然使用**随机起点**对选中的素材进行二次随机处理 - **两层随机性**(候选选择 + 随机起点)极大增加最终视频的多样性 ### 关键特性 1. **场景多候选**:每个场景可以添加多个候选视频素材 2. **防重复机制**:同一场景内的候选视频不能重复 3. **智能填充**: - 一键自动为每个场景添加多个候选 - 支持从素材库快速选择 4. **随机生成**:批量混剪时从每个场景的候选中随机选择 5. **可视化展示**:清晰展示每个场景的候选数量和使用状态 ## 技术架构调整 ### 前端变更 **文件位置:** `frontend/app/web-gold/src/views/material/Mix.vue` **主要改动:** #### 1. 数据结构重构 ```javascript // 原有结构(单一素材) const scene = { fileId: 123, fileUrl: 'xxx.mp4' } // 新结构(多候选) const scene = { index: 0, duration: 3, candidates: [ {fileId: 123, fileUrl: 'xxx1.mp4', fileDuration: 60}, {fileId: 124, fileUrl: 'xxx2.mp4', fileDuration: 45}, {fileId: 125, fileUrl: 'xxx3.mp4', fileDuration: 55} ] } ``` #### 2. 场景格子 UI 更新 - **候选数量标签**:在场景格子上方显示 `候选 3/10` - **候选列表预览**:悬停时显示候选素材的缩略图列表 - **状态指示**: - 空场景:虚线边框,提示"点击选择" - 已填充:实线边框,显示候选数量徽标 - 部分填充:不同颜色标识 - **移除按钮**:每个候选右上角显示删除按钮 #### 3. 交互流程优化 - **点击场景格子** → 打开候选选择弹窗 - **弹窗内容**: - 顶部显示:`场景1 - 已选择 3/10 个候选` - 主体区域:素材库网格(支持多选) - 底部操作:`全选` `反选` `确定` `取消` - **批量操作**: - 支持 Ctrl+Click 多选 - 支持 Shift+Click 范围选择 - 一键全选/清空 #### 4. 一键填充增强(核心优化) **功能描述:** 一键填充功能从原有的"随机填充空场景"升级为"智能多候选填充",能够自动为每个场景分配多个不重复的候选素材。 **填充策略选择:** ```javascript // 提供三种填充模式 const FILL_STRATEGIES = { EMPTY_ONLY: 'empty_only', // 仅填充空场景(默认) SUPPLEMENT: 'supplement', // 补充不足场景到3个候选 FULL_FILL: 'full_fill' // 全量重新填充所有场景 } ``` **智能分配算法:** ```javascript /** * 优化后的一键填充逻辑 * @param strategy 填充策略 * @param targetCount 目标候选数量(默认3-5个) */ const autoFillScenes = (strategy = 'empty_only', targetCount = 3) => { // 1. 收集所有可用的素材 const availableMaterials = [...groupFiles.value]; // 2. 统计当前已使用的素材(避免重复) const usedMaterialIds = new Set(); scenes.value.forEach(scene => { scene.candidates.forEach(candidate => { usedMaterialIds.add(candidate.fileId); }); }); // 3. 过滤可用素材(排除已使用的) const unusedMaterials = availableMaterials.filter( material => !usedMaterialIds.has(material.id) ); // 4. 根据策略执行填充 scenes.value.forEach((scene, sceneIndex) => { const currentCount = scene.candidates.length; let needFill = false; let fillCount = targetCount; // 判断是否需要填充 switch (strategy) { case 'empty_only': needFill = currentCount === 0; break; case 'supplement': needFill = currentCount < targetCount; fillCount = targetCount - currentCount; break; case 'full_fill': needFill = true; fillCount = targetCount; break; } if (needFill && unusedMaterials.length > 0) { // 5. 为当前场景随机选择素材(确保不重复) const selectedMaterials = randomlySelectMaterials( fillCount, unusedMaterials, sceneIndex // 使用场景索引作为随机种子的一部分 ); // 6. 添加到场景候选列表 scene.candidates.push(...selectedMaterials); // 7. 从可用素材中移除已选择的(避免分配给其他场景) selectedMaterials.forEach(selected => { const index = unusedMaterials.findIndex(m => m.id === selected.id); if (index > -1) { unusedMaterials.splice(index, 1); } }); } }); // 8. 显示填充结果提示 showFillResultNotification(); } /** * 随机选择素材工具函数 * @param count 需要选择的数量 * @param materials 素材池 * @param seed 随机种子(基于场景索引) * @returns 选中的素材数组 */ const randomlySelectMaterials = (count, materials, seed) => { // 使用Fisher-Yates洗牌算法确保随机性 const shuffled = [...materials]; // 基于种子创建确定性随机(同一场景索引结果一致) const random = createDeterministicRandom(seed); // 洗牌 for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } // 返回前N个 return shuffled.slice(0, Math.min(count, shuffled.length)); } ``` **防重复机制(优化):** 1. **场景内去重**:确保同一场景内的候选素材不重复(必须) 2. **跨场景复用**(可选):允许同一素材在不同场景中出现 - 优点:提高素材利用率,适合素材库不足的场景 - 缺点:可能降低视频差异性 - 配置项:用户可选择"严格模式"(禁止跨场景重复)或"宽松模式"(允许跨场景重复) 3. **实时更新**:每次填充后立即更新已使用素材列表 4. **视觉反馈**: - 严格模式:已使用素材显示禁用状态 - 宽松模式:已使用素材显示使用次数标记(如"已使用 2 次") **数量控制逻辑:** - **默认数量**:每个场景填充 3 个候选 - **自适应调整**:根据素材库总量动态调整 - 素材库 < 10个:每个场景 1-2个候选 - 素材库 10-50个:每个场景 3-4个候选 - 素材库 > 50个:每个场景 4-5个候选 - **上限保护**:单个场景最多 10 个候选 **用户体验优化:** - **进度提示**:填充过程中显示进度条 - **结果反馈**:填充完成后显示"已为X个场景填充Y个候选" - **撤销操作**:支持一键撤销最近的填充操作 - **智能建议**:根据素材库情况建议最佳填充策略 **边界情况处理:** 1. **素材库不足场景**: ```javascript // 场景:5个场景,每个需要3个候选,但素材库只有10个素材 // 解决方案: // 1. 自动切换到"宽松模式",允许跨场景复用 // 2. 调整目标数量:根据素材库/场景数计算最优分配 // 3. 提示用户:"素材库不足,已自动调整为宽松模式" ``` 2. **素材库为空**: - 提示"素材库为空,请先上传素材" - 禁用一键填充按钮 - 提供快速跳转链接到素材上传页 3. **场景数过多**: - 当场景数 × 目标候选数 > 素材库数量时 - 自动建议减少场景数或增加素材库 - 提供"智能合并场景"建议 4. **批量操作确认**: - 全选/清空等操作前显示确认对话框 - 显示影响范围:如"将影响 5 个场景,共 15 个候选" - 提供预览功能 5. **数据一致性检查**: - 页面刷新后自动恢复场景配置 - 检测并修复损坏的场景数据 - 提示用户进行数据同步 **示例场景:** ``` 素材库:[A, B, C, D, E, F, G, H, I, J] (10个素材) 场景数:3个场景 目标:每个场景3个候选 填充结果: - 场景1:[A, D, G] - 场景2:[B, E, H] - 场景3:[C, F, I] 剩余素材:[J] (未使用,避免浪费) ``` #### 5. 候选管理功能 - **添加候选**:从素材库选择 → 检查重复 → 添加到候选列表 - **移除候选**:点击候选右上角 × → 从列表中移除 - **查看候选详情**:点击场景格子 → 弹窗显示所有候选详情 - **清空场景**:点击"清空"按钮 → 移除所有候选 #### 6. 防重复验证 - **前端实时检查**:选择素材时检查是否已存在于候选列表 - **视觉反馈**:已选择的素材显示禁用状态或"已选择"标记 - **提示信息**:尝试添加重复素材时显示提示"该素材已在候选列表中" #### 7. 数据提交调整 ```javascript // 修改 handleSubmit 中的数据结构 const submitData = { title: formData.value.title, scenes: scenes.value.map(scene => ({ duration: scene.duration, candidates: scene.candidates })), produceCount: formData.value.produceCount, cropMode: formData.value.cropMode }; ``` ### 后端变更 **文件位置:** - `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/mix/vo/MixTaskSaveReqVO.java` - `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/mix/service/MixTaskServiceImpl.java` - `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/media/BatchProduceAlignment.java` **主要改动:** 1. 修改 API 数据结构:支持场景多候选 2. 更新批量混剪逻辑:从每个场景候选中随机选择素材,然后使用随机起点 3. 实现两层随机算法:第一层从候选中选择,第二层使用随机起点 ### 数据库变更 **影响范围:** 无需数据库结构变更 - 前端本地存储场景配置 - 后端通过 JSON 传递候选数据 ## 预期效果 ### 用户体验提升 1. **多样性提升**:批量混剪的视频内容差异显著增大 2. **操作便捷性**:一键填充和批量选择功能 3. **可视化体验**:清晰的场景候选展示 ### 技术收益 1. **代码复用**:保持现有框架结构 2. **性能优化**:随机选择算法高效 3. **向后兼容**:可选模式,不影响现有功能 ## 风险评估 ### 技术风险 - **中等风险**:需要修改前后端多个文件 - **兼容性**:需要确保现有功能不受影响 ### 缓解措施 1. 渐进式迁移:保留现有模式作为备选 2. 充分测试:覆盖各种使用场景 3. 回滚方案:保留现有代码分支 ## 实施计划 ### 阶段一:数据结构设计 - [ ] 设计新的前后端数据结构 - [ ] 定义 API 接口规范 ### 阶段二:前端实现 - [ ] 修改 Mix.vue 组件 - [ ] 更新数据处理逻辑 - [ ] 优化用户界面 ### 阶段三:后端实现 - [ ] 更新 VO 对象 - [ ] 修改混剪服务逻辑 - [ ] 调整随机算法 ### 阶段四:测试验证 - [ ] 单元测试 - [ ] 集成测试 - [ ] 用户验收测试 ## 成功标准 1. **功能完整性**:所有设计功能正常工作 2. **性能指标**:批量混剪性能无明显下降 3. **用户体验**:操作流程顺畅,界面直观 4. **代码质量**:代码结构清晰,有充分注释 ## 相关资源 - **前端代码:** `frontend/app/web-gold/src/views/material/Mix.vue` - **后端 API:** `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/mix/` - **混剪服务:** `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/mix/service/MixTaskServiceImpl.java` - **批量处理:** `yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/media/BatchProduceAlignment.java` ## 决策点 1. **默认候选数量**:建议每个场景默认3-5个候选 2. **最大候选限制**:建议每个场景最多10个候选 3. **随机算法**:基于文件ID和场景索引的确定性随机 4. **UI 展示方式**:采用标签页或下拉列表展示候选 ## 后续优化 1. **智能推荐**:基于视频相似度推荐候选 2. **场景模板**:保存和复用场景配置 3. **批量编辑**:支持跨场景批量操作