feat: 重构 IdentifyFace.vue 为 Hooks 架构
- 新增 hooks/ 目录,包含三个专用 Hook: * useVoiceGeneration - 语音生成和校验逻辑 * useDigitalHumanGeneration - 数字人视频生成逻辑 * useIdentifyFaceController - 协调两个子 Hook 的控制器 - 新增 types/identify-face.ts 完整类型定义 - 重构 IdentifyFace.vue 使用 hooks 架构: * 视图层与业务逻辑分离 * 状态管理清晰化 * 模块解耦,逻辑清晰 - 遵循单一职责原则,每个 Hook 只负责一个领域 - 提升代码可测试性和可维护性 - 支持两种视频素材来源:素材库选择和直接上传 - 实现语音生成优先校验的业务规则 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
## 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 更新
|
||||
Reference in New Issue
Block a user