386 lines
13 KiB
Markdown
386 lines
13 KiB
Markdown
# 混剪场景编排功能重新设计提案
|
||
|
||
## 变更概述
|
||
|
||
**变更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. **批量编辑**:支持跨场景批量操作
|