ARTICLE / 开源项目

补充本地VoxCPM语音克隆provider特性的研究

PR 地址NousResearch/hermes-agent#82961 · 新增 VoxCPM 原生本地 TTS provider(30 语种、语音设计 + 克隆、MPS 加速)

研究摘要

之前,Hermes 的 TTS 格局是"云的好用但花钱且音频出机,本地的不花钱但没有克隆能力也谈不上自然韵律":7 个云 provider(Edge / OpenAI / ElevenLabs / MiniMax / xAI / Mistral / Gemini),3 个本地 provider(Piper / KittenTTS / NeuTTS)全部 CPU-only。现在,OpenBMB 的 VoxCPM2(2026-04 发布、2B 参数)作为一等原生 provider 接入:100% 本地推理、无 API key,支持语音设计(文本描述直接生成新音色)、参考音频克隆、延续克隆三种模式,覆盖 30 种语言含 9 种中文方言,48kHz 输出,Apple Silicon 走 MPS 加速。

实测(Apple M5 Max):语音设计模式合成 27.52 秒音频耗时 48.6 秒(RTF 1.77×),受控提示词生成的音色与描述明显吻合;单元测试 20 个 + 回归套件(Piper 26、命令 provider 22)全绿,含真实模型的端到端测试合计 69 passed。模型加载 10-30 秒的成本由进程级 LRU 缓存(上限 3 条)摊薄,后续调用即时响应。

一、问题背景

1.1 本地 TTS 的能力缺口

既有 3 个本地 provider 的共同短板:CPU-only 推理、无克隆能力、韵律平淡。Piper 支持 44 种语言但没有克隆;想克隆音色只能上云(ElevenLabs 等),音频离机 + 订阅成本。VoxCPM2 是第一个同时满足四项的开放模型:本地离线、无 API key、语音克隆、无参考音频的语音设计,加上 30 语种(含粤语 / 川话 / 吴语 / 东北话 / 河南话 / 陕西话 / 山东话 / 天津话 / 闽南话 9 种中文方言)和 48kHz 录音室级输出。

1.2 为什么选原生 provider 而不是 command provider

Hermes 支持把任意 TTS CLI 包装成 command provider,本 PR 刻意选择原生实现,三个理由:模型缓存——10-30 秒的加载成本要跨调用摊薄,command provider 每次调用都新起 Python 进程;参考音频路径——克隆需要干净地传文件路径,command 模板的 {} 占位符对多文件输入很别扭;流式——voxcpm.generate_streaming 返回生成器,command 子进程输出难以建模分块级流式。改动集中在 tools/tts_tool.py(+230 行),与 Piper / KittenTTS 保持同一代码形态。

二、特性设计

2.1 三种合成模式,按配置存在与否选择

  • 语音设计:文本以 (description) 前缀开头时,按描述合成全新音色,无需参考音频;
  • 参考克隆:配置 reference_wav_path 指向样本 WAV,克隆音色;
  • 延续克隆prompt_wav_path + prompt_text 成对配置,保留音色、节奏、情绪、风格等全部发声细节。两者的互斥依赖在合成前校验,防御操作错误而非依赖模型侧防御。

2.2 与既有 TTS 基础设施的集成

provider 形态与 Piper / KittenTTS 完全对齐:_import_voxcpm() 惰性导入(未安装返回 ImportError)、_check_voxcpm_available() 布尔探测、_resolve_voxcpm_model_path() 配置到路径解析(支持 ~ 展开)、_generate_voxcpm_tts() 与 piper/kittentts 同签名、模块级 _voxcpm_model_cache(由既有 _tts_cache_get_or_load 做 LRU 限界)、elif provider == "voxcpm" 分发分支。配置项全部走 config.yaml(无新环境变量):model、device(auto / cpu / mps / cuda)、local_files_only、inference_timesteps。输出走既有 _repair_ogg_container + ffmpeg 转换路径,Telegram 语音气泡直接可用。文本上限 4000 字符,超长自动分块。依赖是可选的——Hermes 没有 voxcpm 也能正常启动。

2.3 安全设计

模型完全本地运行且 local_files_only: true 默认跳过远端下载;配置路径在加载前做存在性校验;所有配置值先做类型解析(float/int/bool)再使用;LRU 缓存上限 3 条防内存膨胀;4000 字符上限 + 自动分块防长文本 DoS;缺包或缺模型时大声失败,不存在静默回退到网络的路径。

三、实测结果

3.1 测试套件

套件结果
tests/tools/test_tts_voxcpm.py(20 单元 + 1 E2E,单元用确定性 mock)20 passed
Piper 回归26 passed
命令 provider 回归(含 kokoro 改名同步)22 passed
含真实模型 E2E 的全量69 passed(52.63s,含模型加载与真实合成)

E2E 用例以 voxcpm 包安装 + ~/.hermes/models/VoxCPM2/ 存在 model.safetensors 与 audiovae.pth 为前提,手动运行验证。

3.2 真机手动 E2E(Apple M5 Max, MPS, 2026-08-10)

  • 模型加载 6.7s(热缓存),MPS 设备、float32、48kHz;
  • 语音设计:48.6s 生成 27.52s 音频,RTF 1.77×,RMS 458.8(健康语音信号);
  • 受控提示词(“年轻女性、温柔甜美的声音”):44.0s 生成 23.68s 音频,RMS 470.1,音色与描述明显吻合;
  • 运行中触发两次 voxcpm 内置 retry_badcase 机制(audio_text_ratio=6.37 触发重试),这是模型自带的质量守卫而非缺陷;
  • 输出非确定性:voxcpm 的 _generate() 不接受 seed,真实扩散采样,同输入不同次输出有差异。

四、平台兼容性与能力边界

平台状态说明
macOS Apple Silicon✅ 实测MPS 默认,RTF ~1.8×
macOS Intel✅ 可用CPU,明显更慢
Linux / Windows + NVIDIA✅ 预期CUDA,RTF ~0.3
Linux / Windows CPU✅ 可用慢,建议 inference_timesteps: 6

边界与局限:权重约 5GB + 推理时 5-8GB 内存,磁盘紧张机型不适合;RTF ~1.8× 远慢于云 provider(5-10× 快),延迟敏感的语音气泡工作流仍应留在云端;首次调用 10-30 秒模型加载不可避免;voxcpm ≤1.0.4 在 Apple Silicon 上有 MPS dtype 处理缺陷(静音或失真),需升级到 ≥1.0.5;Python 版本要求 ≥3.10 且 <3.13;HF 部分地区被墙,权重下载推荐 ModelScope 镜像。语音克隆的伦理边界与 ElevenLabs 等任何克隆 provider 同口径,不在本 PR 范围内。该 PR 当前状态为 closed。

五、PR 信息

  • PR 地址:https://github.com/NousResearch/hermes-agent/pull/82961
  • 改动规模:+799 / -7,6 个文件
  • 状态:closed
  • 提交时间:2026-08-10

本文记录 x7peeps 向 Hermes Agent 上游贡献的特性研究,所有数据来自 PR 实测记录。