Files
sionrui/openspec/changes/refactor-identify-face-hooks/specs/identify-face-controller/spec.md
sion123 36195ea55a 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>
2025-12-28 00:19:17 +08:00

4.4 KiB
Raw Blame History

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 更新 identifyStatesessionId、faceId、faceStartTime、faceEndTime
  • AND 设置 identifyState.identified = true

Scenario: 素材时长校验

  • GIVEN 有视频时长和音频时长数据
  • WHEN 调用 validateMaterialDuration(videoDurationMs, audioDurationMs)
  • THEN 检查 videoDurationMs > audioDurationMs
  • AND 更新 materialValidationvideoDuration、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 更新