... | ModelScope | ...
https://github.com/DakeQQ/Text-to-Speech-TTS-ONNX/blob/main/VoxCPM/Export_VoxCPM_ONNX.py - DakeQQ 的版本支持 1.5 的模型转换哦,建议使用他的模型让AI写一份HTTP服务,Salute👍❤️
2026-03-10 15:58:15
UPUDATE: 正在开发 VoxCPM.cpp,目前在 ggml 的 python bindings 下跑通非流式合成了,因此这个 onnx 项目的更新还是得推迟,考虑到 DakeQQ 的版本内存占用更低,更对接大家使用它的版本哦
2026-03-18 11:43:48
UPUDATE: 欢迎试用:https://github.com/bluryar/VoxCPM.cpp
VoxCPM ONNX 是对 OpenBMB/VoxCPM 开源模型的 ONNX 导出与推理扩展项目。支持将 VoxCPM 文本转语音模型导出为 ONNX 格式并提供高效的推理服务,支持 CPU 和 GPU 部署,提供 REST API 接口。
⚠️ 重要声明
- 本项目代码与本文档完全由生成式AI驱动生成!
- 使用本项目需遵守VoxCPM以及相关方面的版权规定
- 当前导出代码因为将所有Decode步骤合并到一个模块中,不得不把固定求解欧拉方程的
timesteps参数(默认为10,但经过测试timesteps=5也是可用的,并且解码速度可大大提升)- 当前导出代码重复导出了两份VoxCPM的权重(Prefill和Decode)
本项目基于 OpenBMB 团队的 VoxCPM 模型,该模型是一个无需分词器的文本转语音系统,具有以下特点:
我们的扩展工作专注于 ONNX 导出和推理优化,使模型更易于部署和使用。
VoxCPM-ONNX/
├── onnx/ # ONNX 导出脚本
│ ├── export_audio_vae_encoder.py
│ ├── export_audio_vae_decoder.py
│ ├── export_voxcpm_prefill.py
│ └── export_voxcpm_decode.py
├── src/
│ ├── onnx_infer/ # ONNX 推理引擎
│ └── server/ # FastAPI 服务
├── export.sh # ONNX 导出主脚本
├── opt.sh # 模型优化脚本
├── docker-compose.yml # Docker 部署配置
├── pyproject.toml # 项目配置和依赖管理
├── uv.lock # uv 依赖锁定文件
└── infer.py # 独立推理脚本
本项目使用 uv 进行环境管理,确保依赖的一致性和可重现性。
使用 uv 创建开发环境:
# 克隆项目后,使用 uv 同步环境
uv sync
# 激活虚拟环境
uv run bash
# 或
source .venv/bin/activate
安装依赖:
开发环境 (完整功能):
uv pip install -e .
# 或
pip install -r pyproject.toml
CPU 推理环境:
uv pip install -r requirement.txt
# 或
pip install -r requirement.txt
GPU 推理环境:
uv pip install -r requirement-gpu.txt
# 或
pip install -r requirement-gpu.txt
从官方 VoxCPM 仓库下载预训练模型(VoxCPM-0.5B):
自动下载(推荐):
from huggingface_hub import snapshot_download
snapshot_download("openbmb/VoxCPM-0.5B")
手动下载:
# 创建模型目录
mkdir -p VoxCPM-0.5B
# 下载模型文件到该目录
# 访问 https://huggingface.co/openbmb/VoxCPM-0.5B 获取模型文件
可选增强模型(用于语音增强和提示处理):
from modelscope import snapshot_download
snapshot_download('iic/speech_zipenhancer_ans_multiloss_16k_base')
snapshot_download('iic/SenseVoiceSmall')
使用一键导出脚本将 PyTorch 模型导出为 ONNX 格式:
# 基本用法
bash export.sh
# 自定义参数
MODEL_PATH=./VoxCPM-0.5B OUTPUT_DIR=./onnx_models TIMESTEPS=10 CFG_VALUE=2.0 bash export.sh
导出过程将生成以下模型文件:
audio_vae_encoder.onnx - 音频 VAE 编码器audio_vae_decoder.onnx - 音频 VAE 解码器voxcpm_prefill.onnx - VoxCPM 预填充模型voxcpm_decode_step.onnx - VoxCPM 解码步骤模型使用优化脚本对导出的模型进行进一步优化:
bash opt.sh
优化后的模型将保存在 onnx_models_processed/ 目录中。
GPU 版本:
# 确保已安装 NVIDIA Container Toolkit
docker-compose up voxcpm-gpu
CPU 版本:
# 取消 docker-compose.yml 中 voxcpm-cpu 服务的注释
docker-compose up voxcpm-cpu
服务启动后,API 将在以下地址可用:
GPU 版本:
# 设置环境变量
export VOX_OUTPUT_DIR=./outputs
export VOX_SQLITE_PATH=./ref_feats.db
export VOX_DEVICE=cuda
export VOX_DEVICE_ID=0
export VOX_MODELS_DIR=./models/onnx_models_quantized
export VOX_TOKENIZER_DIR=./models/onnx_models_quantized
export PYTHONPATH=./src
# 启动服务
python -m uvicorn src.server.app:app --host 0.0.0.0 --port 8000
# 服务启动后访问
# 📚 交互式API文档: http://localhost:8000/docs
CPU 版本:
# 设置环境变量
export VOX_OUTPUT_DIR=./outputs
export VOX_SQLITE_PATH=./ref_feats.db
export VOX_DEVICE=cpu
export VOX_DEVICE_ID=0
export VOX_MODELS_DIR=./models/onnx_models_quantized
export VOX_TOKENIZER_DIR=./models/onnx_models_quantized
export PYTHONPATH=./src
# 启动服务
python -m uvicorn src.server.app:app --host 0.0.0.0 --port 8000
📚 API文档: 部署Docker服务后,访问 http://<HOST>:<PORT>/docs 即可查看所有接口的交互式文档(Swagger UI)!
健康检查:
GET /health - 检查服务状态和模型加载情况参考音频管理:
POST /ref_feat - 上传参考音频并编码存储特征到数据库文本转语音:
POST /tts - TTS语音生成(POST方式,支持文件上传)GET /tts - TTS语音生成(GET方式,仅URL参数)curl http://localhost:8100/health
响应示例:
{
"status": "ok",
"initialized": true,
"models_dir": "/root/code/VoxCPM/onnx_models",
"device_type": "cuda",
"device_id": 0
}
功能说明: 上传参考音频文件,系统会提取音频特征并持久化存储到 SQLite 数据库中。上传后的参考音频可以通过 feat_id 在后续的 TTS 请求中重复使用。
使用场景:
请求参数:
feat_id (必填): 参考音频的唯一标识符,后续通过此 ID 引用该音频prompt_audio (必填): 参考音频文件 (支持 WAV、MP3 等格式)prompt_text (可选): 参考音频对应的文本内容,有助于提高合成质量使用示例:
curl -X POST http://localhost:8100/ref_feat \
-F "feat_id=my_voice" \
-F "prompt_audio=@reference.wav" \
-F "prompt_text=这是参考文本内容,可以帮助模型更好地理解声音特征"
响应示例:
{
"feat_id": "my_voice",
"patches_shape": [1, 100, 64]
}
持久化存储: 上传的参考音频特征会永久保存在 SQLite 数据库中(路径由 VOX_SQLITE_PATH 环境变量配置),服务重启后仍然可用。
voice 参数作用说明:
"default": 使用系统默认的参考音频进行语音合成feat_id: 使用通过 /ref_feat 上传的参考音频进行语音克隆使用场景:
请求示例:
# 使用默认声音
curl -X POST http://localhost:8100/tts \
-F "input=你好,这是一个测试文本。" \
-F "voice=default" \
-F "response_format=mp3"
# 使用自定义参考声音(需要先通过 /ref_feat 上传)
curl -X POST http://localhost:8100/tts \
-F "input=使用自定义声音合成这段文本。" \
-F "voice=my_custom_voice" \
-F "response_format=mp3"
# 完整参数示例
curl -X POST http://localhost:8100/tts \
-F "input=你好,这是一个测试文本。" \
-F "voice=my_voice" \
-F "response_format=mp3" \
-F "speed=1.0" \
-F "min_len=2" \
-F "max_len=2000" \
-F "cfg_value=2.0" \
--output output.mp3
voice 参数说明: 与 POST 方式相同,支持 "default"、自定义 feat_id 或留空。
使用示例:
# 使用默认声音
curl "http://localhost:8100/tts?input=你好,世界!&voice=default&response_format=mp3" \
--output output.mp3
# 使用自定义参考声音
curl "http://localhost:8100/tts?input=使用自定义声音合成这段文本。&voice=my_custom_voice&response_format=wav" \
--output custom_output.wav
# 不使用参考音频(基础合成)
curl "http://localhost:8100/tts?input=基础语音合成测试&response_format=mp3" \
--output basic_output.mp3
通用参数:
input (必填): 要转换的文本内容voice: 参考音频ID,支持 "default" 或自定义IDresponse_format: 输出格式 (mp3, wav, opus, aac, flac, pcm),默认 mp3speed: 语速 (占位符,暂不支持变速)prompt_text: 参考音频对应的文本内容min_len: 最小音频长度,默认 2max_len: 最大音频长度,默认 2000cfg_value: CFG系数,默认 2.0import requests
# 上传参考音频文件
with open("my_reference_audio.wav", "rb") as f:
files = {"prompt_audio": f}
data = {
"feat_id": "speaker_john", # 自定义标识符
"prompt_text": "这是参考音频的文本内容"
}
response = requests.post("http://localhost:8100/ref_feat", files=files, data=data)
if response.status_code == 200:
print(f"参考音频上传成功: {response.json()}")
# 输出: {'feat_id': 'speaker_john', 'patches_shape': [1, 100, 64]}
else:
print(f"上传失败: {response.text}")
import requests
# 使用已上传的参考音频进行语音合成
response = requests.post(
"http://localhost:8100/tts",
data={
"input": "使用约翰的声音合成这段文本。",
"voice": "speaker_john", # 使用步骤1中上传的参考音频ID
"response_format": "mp3",
"cfg_value": 2.0
}
)
if response.status_code == 200:
with open("john_voice_output.mp3", "wb") as f:
f.write(response.content)
print("语音合成成功,文件已保存为 john_voice_output.mp3")
else:
print(f"合成失败: {response.text}")
import requests
# 检查服务状态和已上传的参考音频
response = requests.get("http://localhost:8100/health")
health_info = response.json()
if health_info["initialized"]:
print("服务正常运行")
print(f"模型目录: {health_info['models_dir']}")
print(f"设备类型: {health_info['device_type']}")
else:
print(f"服务未初始化: {health_info.get('error', '未知错误')}")
import requests
# GET方式简单请求
response = requests.get(
"http://localhost:8100/tts",
params={
"input": "欢迎使用 VoxCPM ONNX 文本转语音服务。",
"voice": "default",
"response_format": "wav"
}
)
# 保存音频文件
with open("output.wav", "wb") as f:
f.write(response.content)
import requests
# 上传参考音频
with open("reference.wav", "rb") as f:
files = {"prompt_audio": f}
data = {
"feat_id": "my_custom_voice",
"prompt_text": "这是参考音频的文本内容"
}
response = requests.post("http://localhost:8100/ref_feat", files=files, data=data)
print(response.json())
import requests
# 使用已上传的参考音频
response = requests.post(
"http://localhost:8100/tts",
data={
"input": "使用自定义声音合成这段文本。",
"voice": "my_custom_voice",
"response_format": "mp3"
}
)
with open("custom_voice_output.mp3", "wb") as f:
f.write(response.content)
| 变量名 | 说明 | 默认值 |
|---|---|---|
VOX_OUTPUT_DIR | 输出音频文件目录 | ./outputs |
VOX_SQLITE_PATH | 参考特征数据库路径 | ./ref_feats.db |
VOX_DEVICE | 推理设备 (cpu/cuda) | cuda |
VOX_DEVICE_ID | GPU 设备 ID | 0 |
VOX_MODELS_DIR | ONNX 模型目录 | ./models/onnx_models_quantized |
VOX_TOKENIZER_DIR | 分词器目录 | ./models/onnx_models_quantized |
VOX_KEEP_AUDIO_FILES | 是否保留生成的音频文件 | false |
PYTHONPATH | Python 模块路径 | ./src |
在运行 export.sh 时,可以通过环境变量自定义以下参数:
| 变量名 | 说明 | 默认值 |
|---|---|---|
MODEL_PATH | 原始模型路径 | ./VoxCPM-0.5B |
OUTPUT_DIR | ONNX 模型输出目录 | ./onnx_models |
OPSET_VERSION | ONNX 算子集版本 | 20 |
AUDIO_LENGTH | 音频长度 | 16000 |
LATENT_LENGTH | 潜变量长度 | 100 |
LATENT_DIM | 潜变量维度 | 64 |
TIMESTEPS | 扩散步数 | 10 |
CFG_VALUE | CFG 系数 | 2.0 |
RTOL | 验证相对容差 | 1e-3 |
ATOL | 验证绝对容差 | 1e-4 |
NUM_TESTS | 验证测试次数 | 5 |
infer.py 脚本提取特征:python infer.py \
--model_dir ./models/onnx_models_quantized \
--ref_audio ./reference.wav \
--ref_text "参考文本内容" \
--feat_id custom_voice
Timesteps 参数固定: 由于将所有 Decode 步骤合并到一个 ONNX 模块中,求解欧拉方程的 timesteps 参数被固定。默认值为 10,但测试表明 timesteps=5 也可用,且能显著提升解码速度。
权重重复导出: 当前导出代码会重复导出两份 VoxCPM 权重(Prefill 和 Decode),这会增加模型文件大小。
模型优化: 建议使用 opt.sh 脚本对导出的模型进行优化,以减少模型大小并提升推理性能。
1. ONNX 导出失败
2. Docker 容器启动失败
3. 推理速度慢
OMP_NUM_THREADS 环境变量opt.sh)4. 音频质量差
cfg_value 参数GPU 优化:
export CUDA_VISIBLE_DEVICES=0
export OMP_NUM_THREADS=4
export ONNXRUNTIME_SESSION_OPTIONS_INTRA_OP_NUM_THREADS=4
CPU 优化:
export OMP_NUM_THREADS=$(nproc)
export ONNXRUNTIME_SESSION_OPTIONS_INTRA_OP_NUM_THREADS=$(nproc)
本项目是 VoxCPM 的 ONNX 导出和推理扩展,专注于:
原始 VoxCPM 项目专注于模型训练和 PyTorch 推理,而本项目专注于生产环境的 ONNX 部署。
# 使用 uv 创建开发环境
uv sync
# 激活虚拟环境
uv run bash
# 或
source .venv/bin/activate
# 安装开发依赖
uv pip install -e .
# 运行测试
pytest tests/
# 代码格式化
black src/
isort src/
src/onnx_infer/ 中添加新的推理模块src/server/app.py 中的 API 接口重要: 本项目代码与本文档完全由生成式AI驱动生成!
如遇到问题,请:
注意: 本项目专注于 ONNX 推理部署,如需原始 PyTorch 模型训练,请参考 VoxCPM 官方仓库。
14 commits
Python
97.3%
Shell
2.2%
... | ModelScope | ...
https://github.com/DakeQQ/Text-to-Speech-TTS-ONNX/blob/main/VoxCPM/Export_VoxCPM_ONNX.py - DakeQQ 的版本支持 1.5 的模型转换哦,建议使用他的模型让AI写一份HTTP服务,Salute👍❤️
2026-03-10 15:58:15
UPUDATE: 正在开发 VoxCPM.cpp,目前在 ggml 的 python bindings 下跑通非流式合成了,因此这个 onnx 项目的更新还是得推迟,考虑到 DakeQQ 的版本内存占用更低,更对接大家使用它的版本哦
2026-03-18 11:43:48
UPUDATE: 欢迎试用:https://github.com/bluryar/VoxCPM.cpp
VoxCPM ONNX 是对 OpenBMB/VoxCPM 开源模型的 ONNX 导出与推理扩展项目。支持将 VoxCPM 文本转语音模型导出为 ONNX 格式并提供高效的推理服务,支持 CPU 和 GPU 部署,提供 REST API 接口。
⚠️ 重要声明
- 本项目代码与本文档完全由生成式AI驱动生成!
- 使用本项目需遵守VoxCPM以及相关方面的版权规定
- 当前导出代码因为将所有Decode步骤合并到一个模块中,不得不把固定求解欧拉方程的
timesteps参数(默认为10,但经过测试timesteps=5也是可用的,并且解码速度可大大提升)- 当前导出代码重复导出了两份VoxCPM的权重(Prefill和Decode)
本项目基于 OpenBMB 团队的 VoxCPM 模型,该模型是一个无需分词器的文本转语音系统,具有以下特点:
我们的扩展工作专注于 ONNX 导出和推理优化,使模型更易于部署和使用。
VoxCPM-ONNX/
├── onnx/ # ONNX 导出脚本
│ ├── export_audio_vae_encoder.py
│ ├── export_audio_vae_decoder.py
│ ├── export_voxcpm_prefill.py
│ └── export_voxcpm_decode.py
├── src/
│ ├── onnx_infer/ # ONNX 推理引擎
│ └── server/ # FastAPI 服务
├── export.sh # ONNX 导出主脚本
├── opt.sh # 模型优化脚本
├── docker-compose.yml # Docker 部署配置
├── pyproject.toml # 项目配置和依赖管理
├── uv.lock # uv 依赖锁定文件
└── infer.py # 独立推理脚本
本项目使用 uv 进行环境管理,确保依赖的一致性和可重现性。
使用 uv 创建开发环境:
# 克隆项目后,使用 uv 同步环境
uv sync
# 激活虚拟环境
uv run bash
# 或
source .venv/bin/activate
安装依赖:
开发环境 (完整功能):
uv pip install -e .
# 或
pip install -r pyproject.toml
CPU 推理环境:
uv pip install -r requirement.txt
# 或
pip install -r requirement.txt
GPU 推理环境:
uv pip install -r requirement-gpu.txt
# 或
pip install -r requirement-gpu.txt
从官方 VoxCPM 仓库下载预训练模型(VoxCPM-0.5B):
自动下载(推荐):
from huggingface_hub import snapshot_download
snapshot_download("openbmb/VoxCPM-0.5B")
手动下载:
# 创建模型目录
mkdir -p VoxCPM-0.5B
# 下载模型文件到该目录
# 访问 https://huggingface.co/openbmb/VoxCPM-0.5B 获取模型文件
可选增强模型(用于语音增强和提示处理):
from modelscope import snapshot_download
snapshot_download('iic/speech_zipenhancer_ans_multiloss_16k_base')
snapshot_download('iic/SenseVoiceSmall')
使用一键导出脚本将 PyTorch 模型导出为 ONNX 格式:
# 基本用法
bash export.sh
# 自定义参数
MODEL_PATH=./VoxCPM-0.5B OUTPUT_DIR=./onnx_models TIMESTEPS=10 CFG_VALUE=2.0 bash export.sh
导出过程将生成以下模型文件:
audio_vae_encoder.onnx - 音频 VAE 编码器audio_vae_decoder.onnx - 音频 VAE 解码器voxcpm_prefill.onnx - VoxCPM 预填充模型voxcpm_decode_step.onnx - VoxCPM 解码步骤模型使用优化脚本对导出的模型进行进一步优化:
bash opt.sh
优化后的模型将保存在 onnx_models_processed/ 目录中。
GPU 版本:
# 确保已安装 NVIDIA Container Toolkit
docker-compose up voxcpm-gpu
CPU 版本:
# 取消 docker-compose.yml 中 voxcpm-cpu 服务的注释
docker-compose up voxcpm-cpu
服务启动后,API 将在以下地址可用:
GPU 版本:
# 设置环境变量
export VOX_OUTPUT_DIR=./outputs
export VOX_SQLITE_PATH=./ref_feats.db
export VOX_DEVICE=cuda
export VOX_DEVICE_ID=0
export VOX_MODELS_DIR=./models/onnx_models_quantized
export VOX_TOKENIZER_DIR=./models/onnx_models_quantized
export PYTHONPATH=./src
# 启动服务
python -m uvicorn src.server.app:app --host 0.0.0.0 --port 8000
# 服务启动后访问
# 📚 交互式API文档: http://localhost:8000/docs
CPU 版本:
# 设置环境变量
export VOX_OUTPUT_DIR=./outputs
export VOX_SQLITE_PATH=./ref_feats.db
export VOX_DEVICE=cpu
export VOX_DEVICE_ID=0
export VOX_MODELS_DIR=./models/onnx_models_quantized
export VOX_TOKENIZER_DIR=./models/onnx_models_quantized
export PYTHONPATH=./src
# 启动服务
python -m uvicorn src.server.app:app --host 0.0.0.0 --port 8000
📚 API文档: 部署Docker服务后,访问 http://<HOST>:<PORT>/docs 即可查看所有接口的交互式文档(Swagger UI)!
健康检查:
GET /health - 检查服务状态和模型加载情况参考音频管理:
POST /ref_feat - 上传参考音频并编码存储特征到数据库文本转语音:
POST /tts - TTS语音生成(POST方式,支持文件上传)GET /tts - TTS语音生成(GET方式,仅URL参数)curl http://localhost:8100/health
响应示例:
{
"status": "ok",
"initialized": true,
"models_dir": "/root/code/VoxCPM/onnx_models",
"device_type": "cuda",
"device_id": 0
}
功能说明: 上传参考音频文件,系统会提取音频特征并持久化存储到 SQLite 数据库中。上传后的参考音频可以通过 feat_id 在后续的 TTS 请求中重复使用。
使用场景:
请求参数:
feat_id (必填): 参考音频的唯一标识符,后续通过此 ID 引用该音频prompt_audio (必填): 参考音频文件 (支持 WAV、MP3 等格式)prompt_text (可选): 参考音频对应的文本内容,有助于提高合成质量使用示例:
curl -X POST http://localhost:8100/ref_feat \
-F "feat_id=my_voice" \
-F "prompt_audio=@reference.wav" \
-F "prompt_text=这是参考文本内容,可以帮助模型更好地理解声音特征"
响应示例:
{
"feat_id": "my_voice",
"patches_shape": [1, 100, 64]
}
持久化存储: 上传的参考音频特征会永久保存在 SQLite 数据库中(路径由 VOX_SQLITE_PATH 环境变量配置),服务重启后仍然可用。
voice 参数作用说明:
"default": 使用系统默认的参考音频进行语音合成feat_id: 使用通过 /ref_feat 上传的参考音频进行语音克隆使用场景:
请求示例:
# 使用默认声音
curl -X POST http://localhost:8100/tts \
-F "input=你好,这是一个测试文本。" \
-F "voice=default" \
-F "response_format=mp3"
# 使用自定义参考声音(需要先通过 /ref_feat 上传)
curl -X POST http://localhost:8100/tts \
-F "input=使用自定义声音合成这段文本。" \
-F "voice=my_custom_voice" \
-F "response_format=mp3"
# 完整参数示例
curl -X POST http://localhost:8100/tts \
-F "input=你好,这是一个测试文本。" \
-F "voice=my_voice" \
-F "response_format=mp3" \
-F "speed=1.0" \
-F "min_len=2" \
-F "max_len=2000" \
-F "cfg_value=2.0" \
--output output.mp3
voice 参数说明: 与 POST 方式相同,支持 "default"、自定义 feat_id 或留空。
使用示例:
# 使用默认声音
curl "http://localhost:8100/tts?input=你好,世界!&voice=default&response_format=mp3" \
--output output.mp3
# 使用自定义参考声音
curl "http://localhost:8100/tts?input=使用自定义声音合成这段文本。&voice=my_custom_voice&response_format=wav" \
--output custom_output.wav
# 不使用参考音频(基础合成)
curl "http://localhost:8100/tts?input=基础语音合成测试&response_format=mp3" \
--output basic_output.mp3
通用参数:
input (必填): 要转换的文本内容voice: 参考音频ID,支持 "default" 或自定义IDresponse_format: 输出格式 (mp3, wav, opus, aac, flac, pcm),默认 mp3speed: 语速 (占位符,暂不支持变速)prompt_text: 参考音频对应的文本内容min_len: 最小音频长度,默认 2max_len: 最大音频长度,默认 2000cfg_value: CFG系数,默认 2.0import requests
# 上传参考音频文件
with open("my_reference_audio.wav", "rb") as f:
files = {"prompt_audio": f}
data = {
"feat_id": "speaker_john", # 自定义标识符
"prompt_text": "这是参考音频的文本内容"
}
response = requests.post("http://localhost:8100/ref_feat", files=files, data=data)
if response.status_code == 200:
print(f"参考音频上传成功: {response.json()}")
# 输出: {'feat_id': 'speaker_john', 'patches_shape': [1, 100, 64]}
else:
print(f"上传失败: {response.text}")
import requests
# 使用已上传的参考音频进行语音合成
response = requests.post(
"http://localhost:8100/tts",
data={
"input": "使用约翰的声音合成这段文本。",
"voice": "speaker_john", # 使用步骤1中上传的参考音频ID
"response_format": "mp3",
"cfg_value": 2.0
}
)
if response.status_code == 200:
with open("john_voice_output.mp3", "wb") as f:
f.write(response.content)
print("语音合成成功,文件已保存为 john_voice_output.mp3")
else:
print(f"合成失败: {response.text}")
import requests
# 检查服务状态和已上传的参考音频
response = requests.get("http://localhost:8100/health")
health_info = response.json()
if health_info["initialized"]:
print("服务正常运行")
print(f"模型目录: {health_info['models_dir']}")
print(f"设备类型: {health_info['device_type']}")
else:
print(f"服务未初始化: {health_info.get('error', '未知错误')}")
import requests
# GET方式简单请求
response = requests.get(
"http://localhost:8100/tts",
params={
"input": "欢迎使用 VoxCPM ONNX 文本转语音服务。",
"voice": "default",
"response_format": "wav"
}
)
# 保存音频文件
with open("output.wav", "wb") as f:
f.write(response.content)
import requests
# 上传参考音频
with open("reference.wav", "rb") as f:
files = {"prompt_audio": f}
data = {
"feat_id": "my_custom_voice",
"prompt_text": "这是参考音频的文本内容"
}
response = requests.post("http://localhost:8100/ref_feat", files=files, data=data)
print(response.json())
import requests
# 使用已上传的参考音频
response = requests.post(
"http://localhost:8100/tts",
data={
"input": "使用自定义声音合成这段文本。",
"voice": "my_custom_voice",
"response_format": "mp3"
}
)
with open("custom_voice_output.mp3", "wb") as f:
f.write(response.content)
| 变量名 | 说明 | 默认值 |
|---|---|---|
VOX_OUTPUT_DIR | 输出音频文件目录 | ./outputs |
VOX_SQLITE_PATH | 参考特征数据库路径 | ./ref_feats.db |
VOX_DEVICE | 推理设备 (cpu/cuda) | cuda |
VOX_DEVICE_ID | GPU 设备 ID | 0 |
VOX_MODELS_DIR | ONNX 模型目录 | ./models/onnx_models_quantized |
VOX_TOKENIZER_DIR | 分词器目录 | ./models/onnx_models_quantized |
VOX_KEEP_AUDIO_FILES | 是否保留生成的音频文件 | false |
PYTHONPATH | Python 模块路径 | ./src |
在运行 export.sh 时,可以通过环境变量自定义以下参数:
| 变量名 | 说明 | 默认值 |
|---|---|---|
MODEL_PATH | 原始模型路径 | ./VoxCPM-0.5B |
OUTPUT_DIR | ONNX 模型输出目录 | ./onnx_models |
OPSET_VERSION | ONNX 算子集版本 | 20 |
AUDIO_LENGTH | 音频长度 | 16000 |
LATENT_LENGTH | 潜变量长度 | 100 |
LATENT_DIM | 潜变量维度 | 64 |
TIMESTEPS | 扩散步数 | 10 |
CFG_VALUE | CFG 系数 | 2.0 |
RTOL | 验证相对容差 | 1e-3 |
ATOL | 验证绝对容差 | 1e-4 |
NUM_TESTS | 验证测试次数 | 5 |
infer.py 脚本提取特征:python infer.py \
--model_dir ./models/onnx_models_quantized \
--ref_audio ./reference.wav \
--ref_text "参考文本内容" \
--feat_id custom_voice
Timesteps 参数固定: 由于将所有 Decode 步骤合并到一个 ONNX 模块中,求解欧拉方程的 timesteps 参数被固定。默认值为 10,但测试表明 timesteps=5 也可用,且能显著提升解码速度。
权重重复导出: 当前导出代码会重复导出两份 VoxCPM 权重(Prefill 和 Decode),这会增加模型文件大小。
模型优化: 建议使用 opt.sh 脚本对导出的模型进行优化,以减少模型大小并提升推理性能。
1. ONNX 导出失败
2. Docker 容器启动失败
3. 推理速度慢
OMP_NUM_THREADS 环境变量opt.sh)4. 音频质量差
cfg_value 参数GPU 优化:
export CUDA_VISIBLE_DEVICES=0
export OMP_NUM_THREADS=4
export ONNXRUNTIME_SESSION_OPTIONS_INTRA_OP_NUM_THREADS=4
CPU 优化:
export OMP_NUM_THREADS=$(nproc)
export ONNXRUNTIME_SESSION_OPTIONS_INTRA_OP_NUM_THREADS=$(nproc)
本项目是 VoxCPM 的 ONNX 导出和推理扩展,专注于:
原始 VoxCPM 项目专注于模型训练和 PyTorch 推理,而本项目专注于生产环境的 ONNX 部署。
# 使用 uv 创建开发环境
uv sync
# 激活虚拟环境
uv run bash
# 或
source .venv/bin/activate
# 安装开发依赖
uv pip install -e .
# 运行测试
pytest tests/
# 代码格式化
black src/
isort src/
src/onnx_infer/ 中添加新的推理模块src/server/app.py 中的 API 接口重要: 本项目代码与本文档完全由生成式AI驱动生成!
如遇到问题,请:
注意: 本项目专注于 ONNX 推理部署,如需原始 PyTorch 模型训练,请参考 VoxCPM 官方仓库。
14 commits
Python
97.3%
Shell
2.2%