跳到主内容
快讯直播
AI智模界
教程

用 Velum 把 CosyVoice 部署成本地语音克隆推理服务

CosyVoice 是开源的中文语音合成模型,几秒参考音频就能克隆音色;Velum 负责把它从「一个能跑通的脚本」变成「一个有接口、有日志、能挂到你现有应用后面的推理服务」。下面这条路径从零开始把两者串起来,走完之后用一条 curl 就能听到目标音色合成的句子。

需要先说明一句:CosyVoice 与 Velum 都迭代较快,本文涉及的目录名、配置字段、启动参数以各自官方仓库当前版本为准,思路和排查方法是通用的。

适用场景

适合这几类情况:语音合成数据不方便出内网;不想按调用量付费或受第三方额度限制;需要固定使用某个特定说话人的音色(自己的、主播的、企业代言人的);以及要给内部应用提供一个统一的 TTS 接口,希望在模型前面加一层鉴权、限流和日志。

不太适合:对延迟有极端要求、或者需要商业级 SLA 兜底的对外产品。本地部署的稳定性取决于这台机器和你的运维水平,Velum 能帮你把服务管起来,但做不了机器本身的冗余。

环境与前置条件

项目建议
操作系统Ubuntu 20.04 及以上的 LTS 版本,或同级 Linux 发行版;Windows 建议走 WSL2
Python3.10,用 conda 或 venv 隔离,不要用系统自带 Python
CUDA / 驱动与所选 PyTorch 版本匹配;CPU 也能推理,但速度会慢到不适合当服务
GPU 显存8GB 起步比较稳妥,并发请求会显著抬高占用
内存16GB 起
磁盘预留 30GB 以上,模型权重 + conda 环境 + 缓存加起来不小
其他git、git-lfs、ffmpeg、curl

网络上有两点要注意:模型权重一般托管在 ModelScope 与 HuggingFace 两处,国内环境用 ModelScope 会顺一些;Velum 必须能访问到 CosyVoice 服务监听的本地端口,如果以容器方式部署,这一点容易踩坑。

分步骤部署

第 1 步:装系统依赖

```bash

sudo apt update

sudo apt install -y git git-lfs ffmpeg curl build-essential

git lfs install

```

这一步在解决两类问题:git-lfs 用来拉取大体积的模型文件,ffmpeg 用来把参考音频转成模型要求的格式。

成功标志:ffmpeg -version 能打印版本信息,git lfs version 有正常输出。

第 2 步:建 Python 环境并安装 PyTorch

```bash

conda create -n cosyvoice python=3.10 -y

conda activate cosyvoice

python -m pip install --upgrade pip

```

PyTorch 的安装命令随 CUDA 版本变化,不要去记,直接打开 pytorch.org 的安装选择器,按你的驱动版本选好,复制当前给出的那条命令执行。

装完立刻验证:

```bash

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

```

输出里既有版本号又是 True,说明 GPU 可用。如果打印 False,先停下排查,多半是显卡驱动与 CUDA 版本不匹配,继续往下走只会在启动推理时再报一次错。

第 3 步:拉取 CosyVoice 代码并装依赖

```bash

cd ~

git clone --recursive <CosyVoice 官方仓库地址>

cd CosyVoice

pip install -r requirements.txt

```

--recursive 不能省略。仓库里带了子模块,漏掉的话不会立刻报错,而是在运行时才提示找不到某个模块,排查起来更麻烦。

依赖里有两类可选组件(文本正则化、声学相关),按官方 README 的说明安装即可。这一层经常卡住,遇到问题看后面的报错一节。

第 4 步:下载模型权重

权重在 ModelScope 和 HuggingFace 都有,选一个源就行。用 ModelScope 命令行工具的话,大致是这样(具体命令以 ModelScope 文档为准):

```bash

pip install modelscope

modelscope download --model <模型仓库名> --local_dir ./pretrained_models/<目录名>

```

也可以用 git-lfs 直接克隆:

```bash

git clone https://www.modelscope.cn/<模型仓库>.git pretrained_models/<目录名>

```

成功标志:pretrained_models/ 下出现目录,里面有 .pt、.onnx 以及若干配置文件,整体体积与官方说明的量级一致。下载中断会留下不完整的文件,重下之前先删干净,否则会出现「文件在但加载报错」的情况。

第 5 步:准备参考音频

音色克隆的效果,八成由这段参考音频决定。

要求:

  • 时长 3 到 10 秒。太短抓不到音色特征,太长容易混进换气声和环境噪声。
  • 单人说话,没有第二个人声、没有背景音乐、没有明显混响。
  • 采样率 16kHz 以上,单声道,wav 格式。

转换命令:

```bash

ffmpeg -i input.mp3 -ac 1 -ar 16000 -c:a pcm_s16le ref.wav

```

转完一定要自己戴耳机听一遍,确认没有爆音、截断、忽大忽小。这段音频后面会被反复使用,值得花时间挑一段干净的。

同时要准备参考文本:把参考音频里说的每个字原样写下来,包括语气词。

第 6 步:先跑通命令行推理

不要一上手就起服务。先用仓库自带的示例脚本确认模型能出声:

```bash

python <官方示例脚本>.py

```

脚本名和参数以官方 README 为准。等到输出目录里出现 wav 文件、播放后音色和内容都符合预期,再往下走。这一步单独跑通,后面出问题时就能快速判断是模型的问题还是服务层的问题。

第 7 步:起 HTTP 推理服务

CosyVoice 仓库的 runtime 目录下通常带有 FastAPI 或 gRPC 的服务示例,可以直接用:

```bash

cd runtime/python/fastapi

python server.py --port 50000 --model_dir <权重目录>

```

参数名以官方示例为准。如果用 uvicorn 拉起:

```bash

uvicorn server:app --host 0.0.0.0 --port 50000

```

成功标志:终端打印出监听地址,且没有 traceback。要让服务常驻,用 systemd 或 supervisor 包一层,不要挂在 SSH 会话里,否则断开连接服务就没了。

第 8 步:用 Velum 接入

Velum 的位置在模型服务前面,把本地的 CosyVoice 注册成一个后端,对外提供带鉴权、限流和日志的统一接口。配置结构大致如下(字段名以官方文档为准):

```yaml

backends:

  • name: cosyvoice-local

type: http

endpoint: http://127.0.0.1:50000

timeout: 120s

health_check: /health

routes:

  • path: /v1/audio/speech

backend: cosyvoice-local

```

几个要点:

  • timeout 要放大。语音合成是典型的慢请求,长文本尤其慢,默认的 30 秒经常不够。
  • 健康检查路径必须和 CosyVoice 服务实际暴露的一致。路径写错的表现是「模型服务明明在跑,Velum 却一直标记后端不可用」。
  • 如果 Velum 以容器方式运行,配置里的 127.0.0.1 指的是容器自己,要换成宿主机可达的 IP 或服务名,或者让容器使用 host 网络。
  • 网关超时要比模型侧超时更宽松,否则会出现「合成其实成功了,但网关先断开连接」。

改完重启 Velum,看它的启动日志里有没有后端注册成功的记录。

验证部署是否成功

分三层验证,从下往上,哪一层断了就只查那一层。

第一层,模型服务本身。

```bash

curl -s http://127.0.0.1:50000/health

```

返回 200 或一个表示健康的状态即可,具体路径以服务实现为准。

直接调一次克隆合成:

```bash

curl -X POST http://127.0.0.1:50000/inference_zero_shot \

-H "Content-Type: application/json" \

-d '{"tts_text":"今天天气不错","prompt_text":"参考音频对应的文字","prompt_wav":"/path/to/ref.wav"}' \

-o out.wav

```

字段名以服务实现为准。out.wav 能被播放器打开、内容正确,第一层就通了。

第二层,Velum 网关层。

```bash

curl -X POST http://127.0.0.1:<velum端口>/v1/audio/speech \

-H "Authorization: Bearer <你的key>" \

-H "Content-Type: application/json" \

-d '{"input":"今天天气不错","voice":"my-voice"}' \

-o out2.wav

```

out2.wav 能正常播放,说明后端注册、路由转发、鉴权都通了。

第三层,端到端。

用几行 Python 模拟业务代码的调用方式,确认接口形状是你想要的:

```python

import requests

r = requests.post(

"http://127.0.0.1:<velum端口>/v1/audio/speech",

json={"input": "测试一句话", "voice": "my-voice"},

headers={"Authorization": "Bearer <你的key>"},

timeout=120,

)

open("test.wav", "wb").write(r.content)

```

test.wav 可以播放,整条链路就通了。

常见报错与解决

报错:ModuleNotFoundError: No module named 'pynini',或安装 pynini 时编译失败

原因:文本正则化依赖 pynini / WeTextProcessing,直接用 pip 安装经常因为缺少相关底层库而失败。

解决:优先用 conda 从 conda-forge 渠道装,再装其余依赖。

```bash

conda install -c conda-forge pynini -y

pip install WeTextProcessing

```

如果只是想让服务先跑起来,也可以在配置里关闭文本正则化,但要清楚代价:数字、日期、金额这类文本的读法会不符合预期。

报错:torch.cuda.OutOfMemoryError 或 CUDA out of memory

原因:并发请求太多,或者单条文本过长导致显存峰值上升,也可能是别的进程占着显存。

解决:

```bash

nvidia-smi # 先看是谁在占显存

export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128

```

同时在 Velum 侧把并发限制到 1 至 2,并对超过阈值的文本强制分块。语音合成属于 GPU 密集任务,并发调高不一定换来更高吞吐,很容易换来一批 OOM。

报错:克隆出来的声音不像本人,或者带电流声、回音

原因:参考音频质量不达标,或者参考文本和音频内容对不上。

解决:按第 5 步的命令重新处理参考音频,确认单声道、16kHz、无背景音。重点检查 prompt_text 是否和 prompt_wav 里说的内容逐字一致——多一个字、少一个语气词都会明显影响效果。截取更干净的一小段重新试。

报错:长文本返回被截断,或者请求直接超时

原因:多数本地推理服务对单次请求的文本长度有隐含上限,而且合成耗时基本随字数线性增长。

解决:在客户端分块,按句号、问号、逗号这类标点切分,每块控制在几十到一两百字,逐块请求后再拼接音频。拼接不能直接把二进制相加,wav 有文件头,要按帧拼:

```python

import numpy as np

import soundfile as sf

chunks = [sf.read(p) for p in paths]

sr = chunks[0][1]

data = np.concatenate([c[0] for c in chunks])

sf.write("merged.wav", data, sr)

```

分块有两个坑要提前知道。一是切分点如果落在句子中间,语气会断,所以按标点切而不是按字数硬切。二是每块单独合成时音色会有细微波动,要求高的话让相邻块之间留一点重叠,再在重叠处做淡入淡出。

报错:Velum 显示后端不可用,或者调用返回 502

原因:健康检查路径写错、端口不通,或者 Velum 在容器里访问不到宿主机服务。

解决:分两层测连通性。

```bash

curl http://127.0.0.1:50000/health # 宿主机上通不通

docker exec -it <velum容器> curl http://<宿主机IP>:50000/health # 容器里通不通

```

第二条不通就是网络模式或地址的问题,把配置里的地址换成宿主机 IP 或正确的服务名。

后续维护

备份。 需要备份三样东西:Velum 的配置文件、参考音频及其对应的参考文本、以及服务如果支持导出音色特征文件则一并保存。模型权重不用备份,重新下载即可,但建议记下用的是哪个模型仓库、哪个版本,否则升级后音色对不上会很难查。

升级。 分两步走,先升推理侧(CosyVoice 及其依赖),再升 Velum。两者靠 HTTP 协议解耦,先动后端一般不会打断现有调用。每次升级前用同一段参考音频、同一句文本跑一次回归,对比新旧输出是否都能接受——模型迭代后音色发生细微变化是常事,提前有心理预期。

日志与监控。 重点盯四个指标:请求排队时长、单次合成耗时、GPU 显存占用、失败率。合成耗时和文本长度强相关,只看平均值意义不大,按文本长度分桶看更准确。

运行策略。 常驻服务用 systemd 管理并配好 restart 策略。GPU 上跑推理容易遇到显存缓慢增长,可以配合定期健康探测做自动摘除,或者设置低峰期定时重启。并发上限保守一点,宁可让请求排队,也不要因为 OOM 让整个服务不可用。

安全。 如果 Velum 对外暴露,务必开启鉴权。另外合成文本往往包含用户隐私,日志里建议只记录长度和耗时,不要落全文。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。