111 lines
4.4 KiB
Markdown
111 lines
4.4 KiB
Markdown
|
|
## ADDED Requirements
|
|||
|
|
|
|||
|
|
### Requirement: useVoiceGeneration Hook
|
|||
|
|
系统 SHALL 提供 `useVoiceGeneration` Hook,封装所有语音生成相关逻辑。
|
|||
|
|
|
|||
|
|
#### Scenario: 初始化语音生成状态
|
|||
|
|
- **GIVEN** 组件挂载时调用 useVoiceGeneration
|
|||
|
|
- **THEN** 返回响应式状态:ttsText(空字符串)、speechRate(1.0)、selectedVoiceMeta(null)、audioState(初始状态)
|
|||
|
|
|
|||
|
|
#### Scenario: 生成配音
|
|||
|
|
- **GIVEN** 用户点击生成配音按钮且 canGenerateAudio 为 true
|
|||
|
|
- **WHEN** 调用 generateAudio 方法
|
|||
|
|
- **THEN** 执行以下流程:
|
|||
|
|
1. 调用 VoiceService.synthesize 生成音频
|
|||
|
|
2. 解析音频时长
|
|||
|
|
3. 验证音频与人脸区间重合度
|
|||
|
|
4. 更新 audioState.generated 和 audioState.durationMs
|
|||
|
|
5. 返回成功或失败结果
|
|||
|
|
|
|||
|
|
#### Scenario: 音频时长校验
|
|||
|
|
- **GIVEN** 音频生成完成且有人脸识别数据
|
|||
|
|
- **WHEN** 调用 validateAudioDuration
|
|||
|
|
- **THEN** 计算音频与人脸区间的重合时长
|
|||
|
|
- **AND** 如果重合时长 >= 2000ms,设置 audioState.validationPassed = true
|
|||
|
|
- **ELSE** 设置 audioState.validationPassed = false 并显示警告消息
|
|||
|
|
|
|||
|
|
### Requirement: useDigitalHumanGeneration Hook
|
|||
|
|
系统 SHALL 提供 `useDigitalHumanGeneration` Hook,封装所有数字人生成相关逻辑。
|
|||
|
|
|
|||
|
|
#### Scenario: 处理视频文件上传
|
|||
|
|
- **GIVEN** 用户上传视频文件(MP4或MOV格式)
|
|||
|
|
- **WHEN** 调用 handleFileUpload 方法
|
|||
|
|
- **THEN** 执行以下流程:
|
|||
|
|
1. 验证文件格式
|
|||
|
|
2. 创建视频预览 URL
|
|||
|
|
3. 重置识别状态
|
|||
|
|
4. 调用 performFaceRecognition 进行人脸识别
|
|||
|
|
5. 更新 videoState 和 identifyState
|
|||
|
|
|
|||
|
|
#### Scenario: 从素材库选择视频
|
|||
|
|
- **GIVEN** 用户点击"从素材库选择"选项
|
|||
|
|
- **WHEN** 选择视频并调用 handleVideoSelect
|
|||
|
|
- **THEN** 执行以下流程:
|
|||
|
|
1. 设置 selectedVideo 到 videoState
|
|||
|
|
2. 重置识别状态
|
|||
|
|
3. 设置 videoFileId
|
|||
|
|
4. 更新 materialValidation.videoDuration
|
|||
|
|
5. 触发人脸识别
|
|||
|
|
|
|||
|
|
#### Scenario: 人脸识别
|
|||
|
|
- **GIVEN** 有视频文件或已选择视频
|
|||
|
|
- **WHEN** 调用 performFaceRecognition
|
|||
|
|
- **THEN** 根据视频来源调用对应API:
|
|||
|
|
- 如果是上传文件:调用 uploadAndIdentifyVideo
|
|||
|
|
- 如果是素材库:调用 identifyUploadedVideo
|
|||
|
|
- **AND** 更新 identifyState:sessionId、faceId、faceStartTime、faceEndTime
|
|||
|
|
- **AND** 设置 identifyState.identified = true
|
|||
|
|
|
|||
|
|
#### Scenario: 素材时长校验
|
|||
|
|
- **GIVEN** 有视频时长和音频时长数据
|
|||
|
|
- **WHEN** 调用 validateMaterialDuration(videoDurationMs, audioDurationMs)
|
|||
|
|
- **THEN** 检查 videoDurationMs > audioDurationMs
|
|||
|
|
- **AND** 更新 materialValidation:videoDuration、audioDuration、isValid
|
|||
|
|
|
|||
|
|
### Requirement: useIdentifyFaceController Hook
|
|||
|
|
系统 SHALL 提供 `useIdentifyFaceController` Hook,协调语音生成和数字人生成逻辑。
|
|||
|
|
|
|||
|
|
#### Scenario: 生成数字人视频
|
|||
|
|
- **GIVEN** 所有必需数据已准备(文案、音色、视频、配音校验通过)
|
|||
|
|
- **WHEN** 调用 generateDigitalHuman 方法
|
|||
|
|
- **THEN** 执行以下流程:
|
|||
|
|
1. 检查 canGenerate 为 true
|
|||
|
|
2. 如果未识别,先执行人脸识别
|
|||
|
|
3. 构建任务数据(taskName、videoFileId、文本、语音参数等)
|
|||
|
|
4. 如果有预生成音频,添加到 pre_generated_audio 字段
|
|||
|
|
5. 调用 createLipSyncTask 提交任务
|
|||
|
|
6. 返回成功或失败结果
|
|||
|
|
|
|||
|
|
#### Scenario: 确保配音校验顺序
|
|||
|
|
- **GIVEN** 用户尝试生成数字人视频
|
|||
|
|
- **WHEN** 还未生成配音或校验未通过
|
|||
|
|
- **THEN** 阻止生成并提示用户先完成配音生成和校验
|
|||
|
|
|
|||
|
|
#### Scenario: 更换视频
|
|||
|
|
- **GIVEN** 用户点击更换视频按钮
|
|||
|
|
- **WHEN** 调用 replaceVideo 方法
|
|||
|
|
- **THEN** 重置所有相关状态:
|
|||
|
|
- videoState(清空上传文件和选中视频)
|
|||
|
|
- identifyState(重置识别结果)
|
|||
|
|
- materialValidation(重置校验结果)
|
|||
|
|
- audioState(重置音频状态)
|
|||
|
|
|
|||
|
|
## MODIFIED Requirements
|
|||
|
|
|
|||
|
|
### Requirement: IdentifyFace.vue 组件重构
|
|||
|
|
原始的 monolithic 组件 MUST 被重构为使用 hooks 的轻量级视图层。
|
|||
|
|
|
|||
|
|
#### Scenario: 视图层职责
|
|||
|
|
- **WHEN** IdentifyFace.vue 渲染时
|
|||
|
|
- **THEN** 只负责:
|
|||
|
|
1. UI 模板渲染(接收 hooks 返回的数据和状态)
|
|||
|
|
2. 事件绑定(将用户操作转发给 hooks 的方法)
|
|||
|
|
3. 计算属性显示(使用 hooks 提供的 computed 值)
|
|||
|
|
- **AND** 不直接包含业务逻辑(全部委托给 hooks)
|
|||
|
|
|
|||
|
|
#### Scenario: 响应式数据绑定
|
|||
|
|
- **GIVEN** hooks 提供的响应式状态
|
|||
|
|
- **WHEN** 组件渲染时
|
|||
|
|
- **THEN** 通过 v-model 和响应式引用直接绑定到 UI 控件
|
|||
|
|
- **AND** 状态变化自动触发 UI 更新
|