9.3 KiB
9.3 KiB
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 自动混合精度
# 旧: _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回调中用 canvasdrawImage截帧- canvas 缩放到 480px 宽再编码(预览窗口最大 280px,节省内存)
canvas.toDataURL("image/jpeg", 0.7)导出- 防御
videoWidth/videoHeight为 0 的边界情况 - try-catch 防 canvas taint,失败返回 null(降级渐变)
isActive标志 +seeked去重标志防止 stale 和重复更新- 截图完成后清理 video 元素释放内存
按需截取(性能优化)
只在样式预览窗口打开时才触发截取:
const materialPosterUrl = useVideoFrameCapture(
showStylePreview ? firstTimelineMaterialUrl : null
);
截取源优先使用时间轴第一段素材(用户拖拽排序后的真实片头),回退到 selectedMaterials[0](未生成配音、时间轴为空时)。
预览背景替换
FloatingStylePreview 有视频帧时直接显示原始画面(不加半透明,保证颜色真实),文字靠描边保证可读性;无视频帧时降级为原紫粉渐变背景。
踩坑记录
- CORS tainted canvas: 素材文件存储在 Supabase Storage (
api.hbyrkj.top),是跨域签名链接。必须设video.crossOrigin = "anonymous"才能让 canvastoDataURL不被 SecurityError 拦截 - 时间轴为空:
useTimelineEditor在audioDuration <= 0(未选配音)时返回空数组,需回退到selectedMaterials[0] - 事件监听顺序: 必须先绑定事件监听再设
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% | 额外依赖 |