204 lines
9.3 KiB
Markdown
204 lines
9.3 KiB
Markdown
## CosyVoice FP16 加速 + 文档更新 + AI改写界面重构 + 标题字幕面板重排与视频帧预览 (Day 28)
|
||
|
||
### 概述
|
||
|
||
CosyVoice 3.0 声音克隆服务开启 FP16 半精度推理,预估提速 30-40%。同步更新 4 个项目文档。重构 AI 改写文案界面(RewriteModal 两步流程 + ScriptExtractionModal 逻辑抽取)。前端将"标题与字幕"面板从第二步移至第四步(素材编辑之后),样式预览窗口背景从紫粉渐变改为视频片头帧截图,实现所见即所得。
|
||
|
||
---
|
||
|
||
## ✅ 改动内容
|
||
|
||
### 1. CosyVoice FP16 半精度加速
|
||
|
||
- **问题**: CosyVoice 3.0 以 FP32 全精度运行,RTF (Real-Time Factor) 约 0.9-1.35x,生成 2 分钟音频需要约 2 分钟
|
||
- **根因**: `AutoModel()` 初始化时未传入 `fp16=True`,LLM 推理和 Flow Matching (DiT) 均在 FP32 下运行
|
||
- **修复**: 一行改动开启 FP16 自动混合精度
|
||
|
||
```python
|
||
# 旧: _model = AutoModel(model_dir=str(MODEL_DIR))
|
||
# 新:
|
||
_model = AutoModel(model_dir=str(MODEL_DIR), fp16=True)
|
||
```
|
||
|
||
- **生效机制**: `CosyVoice3Model` 在 `llm_job()` 和 `token2wav()` 中通过 `torch.cuda.amp.autocast(self.fp16)` 自动将计算转为 FP16
|
||
- **预期效果**:
|
||
- 推理速度提升 30-40%
|
||
- 显存占用降低 ~30%
|
||
- 语音质量基本无损(0.5B 模型 FP16 精度充足)
|
||
- **验证**: 服务重启后自检通过,健康检查 `ready: true`
|
||
|
||
### 2. 文档全面更新 (4 个文件)
|
||
|
||
补充 Day 27 新增的 MuseTalk 混合唇形同步方案、性能优化、Remotion 并发渲染等内容到所有相关文档。
|
||
|
||
#### README.md
|
||
- 项目描述更新为 "LatentSync 1.6 + MuseTalk 1.5 混合唇形同步"
|
||
- 唇形同步功能描述改为混合方案(短视频 LatentSync,长视频 MuseTalk)
|
||
- 技术栈表新增 MuseTalk 1.5
|
||
- 项目结构新增 `models/MuseTalk/`
|
||
- 服务架构表新增 MuseTalk (端口 8011)
|
||
- 文档中心新增 MuseTalk 部署指南链接
|
||
- 性能优化描述新增降频检测 + Remotion 16 并发
|
||
|
||
#### DEPLOY_MANUAL.md
|
||
- GPU 分配说明更新 (GPU0=MuseTalk+CosyVoice, GPU1=LatentSync)
|
||
- 步骤 3 拆分为 3a (LatentSync) + 3b (MuseTalk)
|
||
- 环境变量表新增 7 个 MuseTalk 变量,移除过时的 `DOUYIN_COOKIE`
|
||
- LatentSync 推理步数默认值 20→16
|
||
- 测试运行新增 MuseTalk 启动终端
|
||
- PM2 管理新增 MuseTalk 服务(第 5 项)
|
||
- 端口检查、日志查看命令新增 8011/vigent2-musetalk
|
||
|
||
#### SUBTITLE_DEPLOY.md
|
||
- 技术架构图更新为 LatentSync/MuseTalk 混合路由
|
||
- 新增唇形同步路由说明
|
||
- Remotion 配置表新增 `concurrency` 参数 (默认 16)
|
||
- GPU 分配说明更新
|
||
- 更新日志新增 v1.3.0 条目
|
||
|
||
#### BACKEND_README.md
|
||
- 健康检查接口描述更新为含 LatentSync + MuseTalk + 混合路由阈值
|
||
- 环境变量配置新增 MuseTalk 相关变量
|
||
- 服务集成指南新增"唇形同步混合路由"章节
|
||
|
||
---
|
||
|
||
### 3. AI 改写文案界面重构
|
||
|
||
#### RewriteModal 重构
|
||
|
||
将 AI 改写弹窗改为两步式流程,提升交互体验:
|
||
|
||
**第一步 — 配置与触发**:
|
||
- 自定义提示词输入(可选),自动持久化到 localStorage
|
||
- "开始改写"按钮触发 `/api/ai/rewrite` 请求
|
||
|
||
**第二步 — 结果对比与选择**:
|
||
- 上方:AI 改写结果 + "使用此结果"按钮(紫粉渐变色,醒目)
|
||
- 下方:原文对比 + "保留原文"按钮(灰色低调)
|
||
- 底部:可"重新改写"(重回第一步,保留自定义提示词)
|
||
- ESC 快捷键关闭
|
||
|
||
#### ScriptExtractionModal 逻辑抽取
|
||
|
||
将文案提取模态框的全部业务逻辑抽取到独立 hook `useScriptExtraction`:
|
||
|
||
- **useScriptExtraction.ts** (新建): 管理 URL/文件双模式输入、拖拽上传、提取请求、步骤状态机 (config → processing → result)、剪贴板复制
|
||
- **ScriptExtractionModal.tsx**: 纯展示组件,消费 hook 返回值,新增 ESC/Enter 快捷键
|
||
|
||
#### ScriptEditor 工具栏调整
|
||
|
||
- 按钮组右对齐 (`justify-end`),统一高度 `h-7` 和圆角
|
||
- "历史文案"按钮用灰色 (bg-gray-600) 区分辅助功能
|
||
- "文案提取助手"用紫色 (bg-purple-600) 表示主功能
|
||
- "AI多语言"用绿渐变 (emerald-teal),"AI生成标题标签"用蓝渐变 (blue-cyan)
|
||
- "AI智能改写"和"保存文案"移至文本框下方状态栏
|
||
|
||
---
|
||
|
||
### 4. 标题字幕面板重排 + 视频帧背景预览
|
||
|
||
#### 面板顺序重排
|
||
|
||
将 `<TitleSubtitlePanel>` 从第二步移至第四步(素材编辑之后),使用户在设置标题字幕样式时已经完成了素材选择和时间轴编排。
|
||
|
||
新顺序:
|
||
```
|
||
一、文案提取与编辑(不变)
|
||
二、配音(原三)
|
||
三、素材编辑(原四)
|
||
四、标题与字幕(原二)→ 移到素材编辑之后
|
||
```
|
||
|
||
#### 新建 useVideoFrameCapture hook
|
||
|
||
从视频 URL 截取 0.1s 处帧画面,返回 JPEG data URL:
|
||
|
||
- 创建 `<video>` 元素,设置 `crossOrigin="anonymous"`(素材存储在 Supabase Storage 跨域地址)
|
||
- 先绑定 `loadedmetadata` / `canplay` / `seeked` / `error` 事件监听,再设 src(避免事件丢失)
|
||
- `loadedmetadata` 或 `canplay` 触发后 seek 到 0.1s,`seeked` 回调中用 canvas `drawImage` 截帧
|
||
- canvas 缩放到 480px 宽再编码(预览窗口最大 280px,节省内存)
|
||
- `canvas.toDataURL("image/jpeg", 0.7)` 导出
|
||
- 防御 `videoWidth/videoHeight` 为 0 的边界情况
|
||
- try-catch 防 canvas taint,失败返回 null(降级渐变)
|
||
- `isActive` 标志 + `seeked` 去重标志防止 stale 和重复更新
|
||
- 截图完成后清理 video 元素释放内存
|
||
|
||
#### 按需截取(性能优化)
|
||
|
||
只在样式预览窗口打开时才触发截取:
|
||
|
||
```typescript
|
||
const materialPosterUrl = useVideoFrameCapture(
|
||
showStylePreview ? firstTimelineMaterialUrl : null
|
||
);
|
||
```
|
||
|
||
截取源优先使用**时间轴第一段素材**(用户拖拽排序后的真实片头),回退到 `selectedMaterials[0]`(未生成配音、时间轴为空时)。
|
||
|
||
#### 预览背景替换
|
||
|
||
`FloatingStylePreview` 有视频帧时直接显示原始画面(不加半透明,保证颜色真实),文字靠描边保证可读性;无视频帧时降级为原紫粉渐变背景。
|
||
|
||
#### 踩坑记录
|
||
|
||
1. **CORS tainted canvas**: 素材文件存储在 Supabase Storage (`api.hbyrkj.top`),是跨域签名链接。必须设 `video.crossOrigin = "anonymous"` 才能让 canvas `toDataURL` 不被 SecurityError 拦截
|
||
2. **时间轴为空**: `useTimelineEditor` 在 `audioDuration <= 0`(未选配音)时返回空数组,需回退到 `selectedMaterials[0]`
|
||
3. **事件监听顺序**: 必须先绑定事件监听再设 `video.src`,否则快速加载时事件可能丢失
|
||
|
||
---
|
||
|
||
## 📁 修改文件清单
|
||
|
||
| 文件 | 改动 |
|
||
|------|------|
|
||
| `models/CosyVoice/cosyvoice_server.py` | `AutoModel()` 新增 `fp16=True` 参数 |
|
||
| `README.md` | 混合唇形同步描述、技术栈、服务架构、项目结构更新 |
|
||
| `Docs/DEPLOY_MANUAL.md` | MuseTalk 部署步骤、环境变量、PM2 管理、端口检查 |
|
||
| `Docs/SUBTITLE_DEPLOY.md` | 架构图、Remotion concurrency、GPU 分配、更新日志 |
|
||
| `Docs/BACKEND_README.md` | 健康检查、环境变量、混合路由章节 |
|
||
| `frontend/.../RewriteModal.tsx` | 两步式改写流程(自定义提示词 → 结果对比) |
|
||
| `frontend/.../script-extraction/useScriptExtraction.ts` | **新建** — 文案提取逻辑 hook |
|
||
| `frontend/.../ScriptExtractionModal.tsx` | 纯展示组件,消费 hook,新增快捷键 |
|
||
| `frontend/.../ScriptEditor.tsx` | 工具栏右对齐 + 按钮分色 + 改写/保存移至底部 |
|
||
| `frontend/.../useVideoFrameCapture.ts` | **新建** — 视频帧截取 hook,crossOrigin + canvas 缩放 |
|
||
| `frontend/.../useHomeController.ts` | 新增 useMemo 计算素材 URL,调用帧截取 hook,showStylePreview 门控 |
|
||
| `frontend/.../HomePage.tsx` | 面板重排(二↔四互换),编号更新,透传 materialPosterUrl |
|
||
| `frontend/.../TitleSubtitlePanel.tsx` | 编号"二"→"四",新增 previewBackgroundUrl prop |
|
||
| `frontend/.../FloatingStylePreview.tsx` | 新增 previewBackgroundUrl prop,条件渲染视频帧/渐变背景 |
|
||
|
||
---
|
||
|
||
## 🔍 验证
|
||
|
||
- CosyVoice 重启成功,健康检查 `{"ready": true}`
|
||
- 自检推理通过(7.2s for "你好")
|
||
- FP16 通过 `torch.cuda.amp.autocast(self.fp16)` 在 LLM 和 Flow Matching 阶段生效
|
||
- `npx tsc --noEmit` — 零错误
|
||
- AI 改写:自定义提示词持久化 → 改写结果 + 原文对比 → "使用此结果"/"保留原文"
|
||
- 文案提取:URL / 文件双模式 → 处理中动画 → 结果填入
|
||
- 面板顺序:一→文案、二→配音、三→素材编辑、四→标题与字幕
|
||
- 样式预览背景:有素材时显示真实视频片头帧,无素材降级紫粉渐变
|
||
- 预览关闭时不触发截取,不浪费资源
|
||
|
||
---
|
||
|
||
## 💡 CosyVoice 性能分析备注
|
||
|
||
### 当前性能基线 (FP32, 优化前)
|
||
|
||
| 文本长度 | 音频时长 | 推理耗时 | RTF |
|
||
|----------|----------|----------|-----|
|
||
| 42 字 | 9.8s | 13.2s | 1.35x |
|
||
| 89 字 | 18.2s | 20.3s | 1.12x |
|
||
| ~530 字 | 115.8s | 107.7s | 0.93x |
|
||
| ~670 字 | 143.5s | 131.6s | 0.92x |
|
||
|
||
### 未来可选优化(收益递减,暂不实施)
|
||
|
||
| 优化项 | 预期提升 | 复杂度 |
|
||
|--------|----------|--------|
|
||
| TensorRT (DiT 模块) | +20-30% | 需编译 .plan 引擎 |
|
||
| torch.compile() | +10-20% | 一行代码,但首次编译慢 |
|
||
| vLLM (LLM 模块) | +10-15% | 额外依赖 |
|