Standalone C++ inference project for VoxCPM models built on top of ggml.
This directory now serves as the standalone repository root for VoxCPM.cpp.
third_party/ggml is intended to be maintained as a vendored subtree.third_party/json, third_party/llama.cpp, third_party/whisper.cpp, and third_party/SenseVoice.cpp are kept only as local references and are ignored by this repository.CMakeLists.txt already supports downloading nlohmann_json with FetchContent when third_party/json is absent.VoxCPM2 is now supported on a preliminary basis. The current C++ runtime can load exported VoxCPM2 GGUF weights, run end-to-end inference, use the new reference-mode plumbing, and produce 48kHz output through the AudioVAE V2 path, but quality and parity are still under active validation.Maintainer note: I am currently also developing other GGML inference projects for TTS and OCR models, along with related GUI applications. As a result, many PRs and issues in this repository may be handled with Codex assistance.
A larger Torch-to-GGML runtime refactor is planned. The design direction is documented in:
Why this refactor is needed:
tensor_get -> std::vector -> tensor_set, which become increasingly costly once the model grows or multi-backend execution is involved.The refactor target is not a cosmetic rewrite. The goal is to move VoxCPM.cpp toward a more mature ggml runtime with:
WeightStore and backend-aware loader/runtime skeletonIn short, the project is moving away from a host-side module translation style and toward a contract-first, backend-aware runtime architecture that is easier to verify, optimize, and extend across CPU/CUDA/Vulkan paths.
To help accelerate that work, I also plan to use ClaudeCode Opus 4.6 for a larger code rewrite pass focused on improving maintainability, clarifying runtime/module boundaries, and reducing the amount of legacy glue code that accumulated during the initial bring-up phase.
cmake -B build
cmake --build build
Enable the ggml CUDA backend at configure time only if you want to run with --backend cuda:
cmake -B build-cuda \
-DVOXCPM_CUDA=ON \
-DVOXCPM_BUILD_BENCHMARK=OFF \
-DVOXCPM_BUILD_TESTS=OFF \
-DCMAKE_CUDA_ARCHITECTURES=89
cmake --build build-cuda
If you want to keep both CPU and CUDA builds, use separate build directories such as build and build-cuda.
Important:
-DVOXCPM_CUDA=ON is only needed when you want to use --backend cuda.-DCMAKE_CUDA_ARCHITECTURES=89 is only an example for RTX 40-series GPUs.-DCMAKE_CUDA_ARCHITECTURES to match your own GPU architecture.86 for many RTX 30-series GPUs89 for many RTX 40-series GPUsIf you are unsure, check your GPU model first instead of copying 89 blindly.
./build/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cpu \
--threads 8
./build/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cpu \
--threads 8 \
--inference-timesteps 10 \
--cfg-value 2.0
./build-cuda/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cuda \
--threads 8 \
--inference-timesteps 10 \
--cfg-value 2.0
voxcpm_tts currently supports --backend {cpu|cuda|vulkan|auto}.
voxcpm-server now exposes a single-port HTTP API for:
POST /v1/voicesGET /v1/voices/{id}DELETE /v1/voices/{id}POST /v1/audio/speechGET /healthzHealth check.
Example response:
{
"status": "ok"
}
POST /v1/voicesRegisters a reusable voice entry by uploading:
id: required, unique voice idtext: required, transcript for the reference audioaudio: required, reference audio fileSuccess response: 201 Created
Returned JSON fields:
idprompt_textprompt_audio_lengthsample_ratepatch_sizefeat_dimcreated_atupdated_atGET /v1/voices/{id}Returns metadata for a previously registered voice id.
Success response: 200 OK
Returned JSON fields:
idprompt_textprompt_audio_lengthsample_ratepatch_sizefeat_dimcreated_atupdated_atDELETE /v1/voices/{id}Deletes a registered voice id.
Success response: 200 OK
Example response:
{
"id": "taiyi",
"deleted": true
}
POST /v1/audio/speechSynthesizes speech from text using a registered voice id.
JSON request fields:
model: required string, must match the configured --model-nameinput: required string, 1 to 4096 charactersvoice: required
"taiyi"{ "id": "taiyi" }response_format: optional, defaults to mp3
mp3, opus, flac, wav, pcmspeed: optional float, range 0.25 to 4.0stream_format: optional, audio or sseinstructions: accepted for compatibility, but non-empty values currently return an errorResponse behavior:
stream_format=audio or omitted:
Content-Type matches response_formatstream_format=sse:
text/event-streamaudio.delta event contains a self-contained chunk encoded with the requested response_formatevent: audio.deltaevent: audio.completedServer-side output rate:
--output-sample-rate HZ to voxcpm-server to resample synthesized audio before it is encodedpcm responses, set --output-sample-rate 24000 if your client expects 24 kHz PCMwav, mp3, and opusQueue behavior:
--max-queue503Supported output formats:
mp3: audio/mpegopus: audio/ogg; codecs=opusflac: audio/flacwav: audio/wavpcm: application/octet-streamBuild-time support:
VOXCPM_ENABLE_MP3=ON|OFF
ffmpeg if that path cannot initializeVOXCPM_ENABLE_OPUS=ON|OFF
ffmpeg fallback when enabledffmpeg is unavailable when CMake configures the build, support is disabled and /v1/audio/speech returns 501 for response_format=opusExample outputs:
speech.mp3speech.opusFor CUDA deployment:
cmake -B build-cuda \
-DVOXCPM_CUDA=ON \
-DVOXCPM_BUILD_BENCHMARK=OFF \
-DVOXCPM_BUILD_TESTS=OFF \
-DCMAKE_CUDA_ARCHITECTURES=89
cmake --build build-cuda -j8
This CUDA build is only required if you plan to launch the server with --backend cuda.
If you want --backend cpu, a normal CPU build is enough:
cmake -B build -DVOXCPM_BUILD_BENCHMARK=OFF -DVOXCPM_BUILD_TESTS=OFF
cmake --build build -j8
If you want to explicitly control audio encoder support, add:
cmake -B build -DVOXCPM_BUILD_BENCHMARK=OFF -DVOXCPM_BUILD_TESTS=OFF \
-DVOXCPM_ENABLE_MP3=ON \
-DVOXCPM_ENABLE_OPUS=ON
These options default to ON.
The server auto-creates --voice-dir if it does not exist.
CUDA example:
./build-cuda/examples/voxcpm-server \
--host 127.0.0.1 \
--port 8080 \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--model-name voxcpm-1.5 \
--threads 8 \
--backend cuda \
--voice-dir ./runtime/voices \
--max-queue 8 \
--max-decode-steps 512 \
--output-sample-rate 24000 \
--disable-auth
Use --max-decode-steps when serving long text. If omitted or set to 0, the server keeps the conservative per-backend default decode budget.
CPU example:
./build/examples/voxcpm-server \
--host 127.0.0.1 \
--port 8080 \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--model-name voxcpm-1.5 \
--threads 8 \
--backend cpu \
--voice-dir ./runtime/voices \
--max-queue 8 \
--max-decode-steps 512 \
--output-sample-rate 24000 \
--disable-auth
curl -X POST http://127.0.0.1:8080/v1/voices \
-F "id=taiyi" \
-F "text=对,这就是我,万人敬仰的太乙真人。" \
-F "audio=@./examples/tai_yi_xian_ren.wav"
Example response:
{
"created_at": "2026-03-18T11:32:51Z",
"feat_dim": 64,
"id": "taiyi",
"patch_size": 4,
"prompt_audio_length": 43,
"prompt_text": "对,这就是我,万人敬仰的太乙真人。",
"sample_rate": 44100,
"updated_at": "2026-03-18T11:32:51Z"
}
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "wav",
"speed": 1.0,
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.wav
MP3 example:
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "mp3",
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.mp3
Opus example:
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "opus",
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.opus
"taiyi" in the voice field.instructions is accepted for compatibility but is not implemented in VoxCPM v1.stream_format supports audio and sse; audio.delta events carry the same encoded bytes and format value as the non-streaming path.opus is emitted as an Ogg Opus container, not a raw Opus packet stream.CUDA_VISIBLE_DEVICES only controls GPU visibility.
It does not change response_format, MIME type selection, or which audio encoder is used.examples/voxcpm_tts is still the simplest entry point.Authorization: Bearer <api-key>.501 with a message such as this build does not include opus encoder support.{
"error": {
"message": "Human-readable message",
"type": "invalid_request_error",
"code": "bad_request"
}
}
./scripts/export_quantized_weights.sh
This exports:
Q4_KQ8_0F16+AudioVAE-F16 variantsF32 baseline copyand writes a manifest like logs/quantized_weights_manifest_*.tsv.
CPU:
./scripts/benchmark_exported_weights.sh \
--weights-file ./logs/quantized_weights_manifest_*.tsv \
--backend cpu
CUDA:
./scripts/benchmark_exported_weights.sh \
--weights-file ./logs/quantized_weights_manifest_*.tsv \
--backend cuda
If --weights-file is omitted, the script will automatically pick the latest manifest under logs/.
cd build
ctest --output-on-failure
For configurable model/trace test paths and open-source collaboration setup, see docs/TEST_SETUP.md.
The project keeps local provenance for the current ggml import and patch flow:
https://github.com/ggerganov/ggml.git4773cde162a55f0d10a6a6d7c2ea4378e30e0b01src/ggml-vulkan/ggml-vulkan.cppSee docs/ggml_subtree_maintenance_strategy.md for the longer-term maintenance approach.
https://github.com/DakeQQ/Text-to-Speech-TTS-ONNX, there is still a noticeable gap between the current performance here and their reported results.VoxCPM2 support.ClaudeCode Opus 4.6.A browser-oriented WASM playground scaffold now lives in:
wasm/web/packages/voxcpm-web/web/playground/See docs/wasm_playground.md for the Emscripten build flow and web demo setup.
I also plan to create a dedicated GGML inference repository for https://huggingface.co/fishaudio/s2-pro.
| Model | Quant | Size (MB) | Compression |
|---|---|---|---|
| voxcpm1.5 | F32 | 3392 | 1.00x (baseline) |
| voxcpm1.5 | F16 | 1700 | 1.99x |
| voxcpm1.5 | Q8_0 | 942 | 3.60x |
| voxcpm1.5 | Q4_K | 582 | 5.82x |
| voxcpm-0.5b | F32 | 2779 | 1.00x (baseline) |
| voxcpm-0.5b | F16 | 1394 | 1.99x |
| voxcpm-0.5b | Q8_0 | 766 | 3.62x |
| voxcpm-0.5b | Q4_K | 477 | 5.82x |
| Model | Quant | Model Only | Without Encode | Full Pipeline |
|---|---|---|---|---|
| voxcpm1.5 | Q4_K | 2.395 | 3.395 | 5.598 |
| voxcpm1.5 | Q4_K+AudioVAE-F16 | 1.873 | 2.848 | 4.433 |
| voxcpm1.5 | Q8_0 | 2.086 | 2.982 | 4.291 |
| voxcpm1.5 | Q8_0+AudioVAE-F16 | 2.285 | 3.321 | 5.248 |
| voxcpm1.5 | F16 | 3.257 | 4.366 | 6.263 |
| voxcpm1.5 | F16+AudioVAE-F16 | 2.980 | 3.915 | 5.374 |
| voxcpm1.5 | F32 | 4.820 | 5.737 | 7.494 |
| voxcpm-0.5b | Q4_K | 1.826 | 2.219 | 3.609 |
| voxcpm-0.5b | Q4_K+AudioVAE-F16 | 1.895 | 2.295 | 3.915 |
| voxcpm-0.5b | Q8_0 | 2.155 | 2.546 | 3.873 |
| voxcpm-0.5b | Q8_0+AudioVAE-F16 | 1.913 | 2.284 | 3.638 |
| voxcpm-0.5b | F16 | 2.558 | 2.931 | 4.086 |
| voxcpm-0.5b | F16+AudioVAE-F16 | 2.685 | 3.057 | 4.409 |
| voxcpm-0.5b | F32 | 3.691 | 4.055 | 5.260 |
| Model | Variant | AudioVAE | Model Only | Without Encode | Full Pipeline | Total Time (s) |
|---|---|---|---|---|---|---|
| voxcpm1.5 | Q4_K | mixed | 0.342 | 0.432 | 0.622 | 2.189 |
| voxcpm1.5 | Q4_K+AudioVAE-F16 | f16 | 0.336 | 0.426 | 0.596 | 2.192 |
| voxcpm1.5 | Q8_0 | mixed | 0.320 | 0.411 | 0.596 | 2.002 |
| voxcpm1.5 | Q8_0+AudioVAE-F16 | f16 | 0.308 | 0.397 | 0.559 | 2.148 |
| voxcpm1.5 | F16 | mixed | 0.352 | 0.442 | 0.648 | 1.970 |
| voxcpm1.5 | F16+AudioVAE-F16 | f16 | 0.347 | 0.438 | 0.655 | 1.885 |
| voxcpm1.5 | F32 (baseline) | original | 0.414 | 0.503 | 0.686 | 2.305 |
| voxcpm-0.5b | Q4_K | mixed | 0.401 | 0.442 | 0.550 | 2.067 |
| voxcpm-0.5b | Q4_K+AudioVAE-F16 | f16 | 0.396 | 0.437 | 0.555 | 1.953 |
| voxcpm-0.5b | Q8_0 | mixed | 0.430 | 0.470 | 0.623 | 1.644 |
| voxcpm-0.5b | Q8_0+AudioVAE-F16 | f16 | 0.417 | 0.456 | 0.595 | 1.809 |
| voxcpm-0.5b | F16 | mixed | 0.390 | 0.428 | 0.567 | 1.678 |
| voxcpm-0.5b | F16+AudioVAE-F16 | f16 | 0.392 | 0.430 | 0.565 | 1.718 |
| voxcpm-0.5b | F32 (baseline) | original | 0.500 | 0.539 | 0.680 | 1.903 |
RTF Definitions:
voxcpm1.5 Q4_K+AudioVAE-F16 leads on model-only and without-encode RTF, while voxcpm1.5 Q8_0 has the best full-pipeline RTF; voxcpm-0.5b Q4_K remains the strongest overall CPU choice.Q4_K+AudioVAE-F16 gives the best voxcpm1.5 model-only and without-encode RTF, while Q8_0 gives the best full-pipeline RTF.voxcpm-0.5b Q4_K has the best overall CPU RTF, with Q8_0+AudioVAE-F16 close behind on full-pipeline performance.voxcpm1.5 and voxcpm-0.5b show the worst CPU RTF with F32 baseline weights.3.83-15.02 on CPU to 0.55-0.69 on CUDA in this benchmark set.voxcpm1.5, Q8_0+AudioVAE-F16 gives the best RTF, while F16+AudioVAE-F16 gives the shortest total time; for voxcpm-0.5b, Q4_K gives the best full-pipeline RTF, while Q8_0 gives the shortest total time.Q4_K is not consistently the fastest on CUDA; Q8_0 and F16 are often competitive or better.F16 improves several CUDA runs, especially for voxcpm1.5 Q8_0 and voxcpm-0.5b Q8_0.| Scenario | Recommended Config |
|---|---|
| Production | voxcpm-0.5b Q4_K (477 MB, RTF 3.609) |
| Balanced accuracy | voxcpm1.5 Q8_0 (942 MB, RTF 4.291) |
| Best 1.5B offline prompt pipeline | voxcpm1.5 Q4_K+AudioVAE-F16 (647 MB, RTF 2.848 without encode) |
| Max accuracy baseline | voxcpm1.5 F32 (3392 MB, RTF 7.494) |
| Scenario | Recommended Config |
|---|---|
| Lowest full-pipeline RTF | voxcpm-0.5b Q4_K (477 MB, RTF 0.550) |
| Best 1.5B latency/RTF balance | voxcpm1.5 Q8_0+AudioVAE-F16 (984 MB, RTF 0.559) |
| Smallest CUDA-friendly 1.5B model | voxcpm1.5 Q4_K+AudioVAE-F16 (647 MB, RTF 0.596) |
| Max accuracy baseline | voxcpm1.5 F32 (3392 MB, RTF 0.686) |
CPU test environment:
logs/benchmark_summary_cpu_20260318_092142.txtCUDA test environment:
CUDA0logs/benchmark_summary_cuda_20260318_092028.txtC++
87.0%
TypeScript
5.4%
JavaScript
3.3%
Python
2.3%
Shell
1.4%
Standalone C++ inference project for VoxCPM models built on top of ggml.
This directory now serves as the standalone repository root for VoxCPM.cpp.
third_party/ggml is intended to be maintained as a vendored subtree.third_party/json, third_party/llama.cpp, third_party/whisper.cpp, and third_party/SenseVoice.cpp are kept only as local references and are ignored by this repository.CMakeLists.txt already supports downloading nlohmann_json with FetchContent when third_party/json is absent.VoxCPM2 is now supported on a preliminary basis. The current C++ runtime can load exported VoxCPM2 GGUF weights, run end-to-end inference, use the new reference-mode plumbing, and produce 48kHz output through the AudioVAE V2 path, but quality and parity are still under active validation.Maintainer note: I am currently also developing other GGML inference projects for TTS and OCR models, along with related GUI applications. As a result, many PRs and issues in this repository may be handled with Codex assistance.
A larger Torch-to-GGML runtime refactor is planned. The design direction is documented in:
Why this refactor is needed:
tensor_get -> std::vector -> tensor_set, which become increasingly costly once the model grows or multi-backend execution is involved.The refactor target is not a cosmetic rewrite. The goal is to move VoxCPM.cpp toward a more mature ggml runtime with:
WeightStore and backend-aware loader/runtime skeletonIn short, the project is moving away from a host-side module translation style and toward a contract-first, backend-aware runtime architecture that is easier to verify, optimize, and extend across CPU/CUDA/Vulkan paths.
To help accelerate that work, I also plan to use ClaudeCode Opus 4.6 for a larger code rewrite pass focused on improving maintainability, clarifying runtime/module boundaries, and reducing the amount of legacy glue code that accumulated during the initial bring-up phase.
cmake -B build
cmake --build build
Enable the ggml CUDA backend at configure time only if you want to run with --backend cuda:
cmake -B build-cuda \
-DVOXCPM_CUDA=ON \
-DVOXCPM_BUILD_BENCHMARK=OFF \
-DVOXCPM_BUILD_TESTS=OFF \
-DCMAKE_CUDA_ARCHITECTURES=89
cmake --build build-cuda
If you want to keep both CPU and CUDA builds, use separate build directories such as build and build-cuda.
Important:
-DVOXCPM_CUDA=ON is only needed when you want to use --backend cuda.-DCMAKE_CUDA_ARCHITECTURES=89 is only an example for RTX 40-series GPUs.-DCMAKE_CUDA_ARCHITECTURES to match your own GPU architecture.86 for many RTX 30-series GPUs89 for many RTX 40-series GPUsIf you are unsure, check your GPU model first instead of copying 89 blindly.
./build/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cpu \
--threads 8
./build/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cpu \
--threads 8 \
--inference-timesteps 10 \
--cfg-value 2.0
./build-cuda/examples/voxcpm_tts \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--prompt-audio ./examples/tai_yi_xian_ren.wav \
--prompt-text "对,这就是我,万人敬仰的太乙真人。" \
--text "大家好,我现在正在大可奇奇体验AI科技。" \
--output ./out.wav \
--backend cuda \
--threads 8 \
--inference-timesteps 10 \
--cfg-value 2.0
voxcpm_tts currently supports --backend {cpu|cuda|vulkan|auto}.
voxcpm-server now exposes a single-port HTTP API for:
POST /v1/voicesGET /v1/voices/{id}DELETE /v1/voices/{id}POST /v1/audio/speechGET /healthzHealth check.
Example response:
{
"status": "ok"
}
POST /v1/voicesRegisters a reusable voice entry by uploading:
id: required, unique voice idtext: required, transcript for the reference audioaudio: required, reference audio fileSuccess response: 201 Created
Returned JSON fields:
idprompt_textprompt_audio_lengthsample_ratepatch_sizefeat_dimcreated_atupdated_atGET /v1/voices/{id}Returns metadata for a previously registered voice id.
Success response: 200 OK
Returned JSON fields:
idprompt_textprompt_audio_lengthsample_ratepatch_sizefeat_dimcreated_atupdated_atDELETE /v1/voices/{id}Deletes a registered voice id.
Success response: 200 OK
Example response:
{
"id": "taiyi",
"deleted": true
}
POST /v1/audio/speechSynthesizes speech from text using a registered voice id.
JSON request fields:
model: required string, must match the configured --model-nameinput: required string, 1 to 4096 charactersvoice: required
"taiyi"{ "id": "taiyi" }response_format: optional, defaults to mp3
mp3, opus, flac, wav, pcmspeed: optional float, range 0.25 to 4.0stream_format: optional, audio or sseinstructions: accepted for compatibility, but non-empty values currently return an errorResponse behavior:
stream_format=audio or omitted:
Content-Type matches response_formatstream_format=sse:
text/event-streamaudio.delta event contains a self-contained chunk encoded with the requested response_formatevent: audio.deltaevent: audio.completedServer-side output rate:
--output-sample-rate HZ to voxcpm-server to resample synthesized audio before it is encodedpcm responses, set --output-sample-rate 24000 if your client expects 24 kHz PCMwav, mp3, and opusQueue behavior:
--max-queue503Supported output formats:
mp3: audio/mpegopus: audio/ogg; codecs=opusflac: audio/flacwav: audio/wavpcm: application/octet-streamBuild-time support:
VOXCPM_ENABLE_MP3=ON|OFF
ffmpeg if that path cannot initializeVOXCPM_ENABLE_OPUS=ON|OFF
ffmpeg fallback when enabledffmpeg is unavailable when CMake configures the build, support is disabled and /v1/audio/speech returns 501 for response_format=opusExample outputs:
speech.mp3speech.opusFor CUDA deployment:
cmake -B build-cuda \
-DVOXCPM_CUDA=ON \
-DVOXCPM_BUILD_BENCHMARK=OFF \
-DVOXCPM_BUILD_TESTS=OFF \
-DCMAKE_CUDA_ARCHITECTURES=89
cmake --build build-cuda -j8
This CUDA build is only required if you plan to launch the server with --backend cuda.
If you want --backend cpu, a normal CPU build is enough:
cmake -B build -DVOXCPM_BUILD_BENCHMARK=OFF -DVOXCPM_BUILD_TESTS=OFF
cmake --build build -j8
If you want to explicitly control audio encoder support, add:
cmake -B build -DVOXCPM_BUILD_BENCHMARK=OFF -DVOXCPM_BUILD_TESTS=OFF \
-DVOXCPM_ENABLE_MP3=ON \
-DVOXCPM_ENABLE_OPUS=ON
These options default to ON.
The server auto-creates --voice-dir if it does not exist.
CUDA example:
./build-cuda/examples/voxcpm-server \
--host 127.0.0.1 \
--port 8080 \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--model-name voxcpm-1.5 \
--threads 8 \
--backend cuda \
--voice-dir ./runtime/voices \
--max-queue 8 \
--max-decode-steps 512 \
--output-sample-rate 24000 \
--disable-auth
Use --max-decode-steps when serving long text. If omitted or set to 0, the server keeps the conservative per-backend default decode budget.
CPU example:
./build/examples/voxcpm-server \
--host 127.0.0.1 \
--port 8080 \
--model-path ./models/quantized/voxcpm1.5-q8_0-audiovae-f16.gguf \
--model-name voxcpm-1.5 \
--threads 8 \
--backend cpu \
--voice-dir ./runtime/voices \
--max-queue 8 \
--max-decode-steps 512 \
--output-sample-rate 24000 \
--disable-auth
curl -X POST http://127.0.0.1:8080/v1/voices \
-F "id=taiyi" \
-F "text=对,这就是我,万人敬仰的太乙真人。" \
-F "audio=@./examples/tai_yi_xian_ren.wav"
Example response:
{
"created_at": "2026-03-18T11:32:51Z",
"feat_dim": 64,
"id": "taiyi",
"patch_size": 4,
"prompt_audio_length": 43,
"prompt_text": "对,这就是我,万人敬仰的太乙真人。",
"sample_rate": 44100,
"updated_at": "2026-03-18T11:32:51Z"
}
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "wav",
"speed": 1.0,
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.wav
MP3 example:
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "mp3",
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.mp3
Opus example:
curl -X POST http://127.0.0.1:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "voxcpm-1.5",
"input": "大家好,我现在正在大可奇奇体验AI科技。",
"voice": "taiyi",
"response_format": "opus",
"stream_format": "audio"
}' \
--output ./voxcpm_taiyi.opus
"taiyi" in the voice field.instructions is accepted for compatibility but is not implemented in VoxCPM v1.stream_format supports audio and sse; audio.delta events carry the same encoded bytes and format value as the non-streaming path.opus is emitted as an Ogg Opus container, not a raw Opus packet stream.CUDA_VISIBLE_DEVICES only controls GPU visibility.
It does not change response_format, MIME type selection, or which audio encoder is used.examples/voxcpm_tts is still the simplest entry point.Authorization: Bearer <api-key>.501 with a message such as this build does not include opus encoder support.{
"error": {
"message": "Human-readable message",
"type": "invalid_request_error",
"code": "bad_request"
}
}
./scripts/export_quantized_weights.sh
This exports:
Q4_KQ8_0F16+AudioVAE-F16 variantsF32 baseline copyand writes a manifest like logs/quantized_weights_manifest_*.tsv.
CPU:
./scripts/benchmark_exported_weights.sh \
--weights-file ./logs/quantized_weights_manifest_*.tsv \
--backend cpu
CUDA:
./scripts/benchmark_exported_weights.sh \
--weights-file ./logs/quantized_weights_manifest_*.tsv \
--backend cuda
If --weights-file is omitted, the script will automatically pick the latest manifest under logs/.
cd build
ctest --output-on-failure
For configurable model/trace test paths and open-source collaboration setup, see docs/TEST_SETUP.md.
The project keeps local provenance for the current ggml import and patch flow:
https://github.com/ggerganov/ggml.git4773cde162a55f0d10a6a6d7c2ea4378e30e0b01src/ggml-vulkan/ggml-vulkan.cppSee docs/ggml_subtree_maintenance_strategy.md for the longer-term maintenance approach.
https://github.com/DakeQQ/Text-to-Speech-TTS-ONNX, there is still a noticeable gap between the current performance here and their reported results.VoxCPM2 support.ClaudeCode Opus 4.6.A browser-oriented WASM playground scaffold now lives in:
wasm/web/packages/voxcpm-web/web/playground/See docs/wasm_playground.md for the Emscripten build flow and web demo setup.
I also plan to create a dedicated GGML inference repository for https://huggingface.co/fishaudio/s2-pro.
| Model | Quant | Size (MB) | Compression |
|---|---|---|---|
| voxcpm1.5 | F32 | 3392 | 1.00x (baseline) |
| voxcpm1.5 | F16 | 1700 | 1.99x |
| voxcpm1.5 | Q8_0 | 942 | 3.60x |
| voxcpm1.5 | Q4_K | 582 | 5.82x |
| voxcpm-0.5b | F32 | 2779 | 1.00x (baseline) |
| voxcpm-0.5b | F16 | 1394 | 1.99x |
| voxcpm-0.5b | Q8_0 | 766 | 3.62x |
| voxcpm-0.5b | Q4_K | 477 | 5.82x |
| Model | Quant | Model Only | Without Encode | Full Pipeline |
|---|---|---|---|---|
| voxcpm1.5 | Q4_K | 2.395 | 3.395 | 5.598 |
| voxcpm1.5 | Q4_K+AudioVAE-F16 | 1.873 | 2.848 | 4.433 |
| voxcpm1.5 | Q8_0 | 2.086 | 2.982 | 4.291 |
| voxcpm1.5 | Q8_0+AudioVAE-F16 | 2.285 | 3.321 | 5.248 |
| voxcpm1.5 | F16 | 3.257 | 4.366 | 6.263 |
| voxcpm1.5 | F16+AudioVAE-F16 | 2.980 | 3.915 | 5.374 |
| voxcpm1.5 | F32 | 4.820 | 5.737 | 7.494 |
| voxcpm-0.5b | Q4_K | 1.826 | 2.219 | 3.609 |
| voxcpm-0.5b | Q4_K+AudioVAE-F16 | 1.895 | 2.295 | 3.915 |
| voxcpm-0.5b | Q8_0 | 2.155 | 2.546 | 3.873 |
| voxcpm-0.5b | Q8_0+AudioVAE-F16 | 1.913 | 2.284 | 3.638 |
| voxcpm-0.5b | F16 | 2.558 | 2.931 | 4.086 |
| voxcpm-0.5b | F16+AudioVAE-F16 | 2.685 | 3.057 | 4.409 |
| voxcpm-0.5b | F32 | 3.691 | 4.055 | 5.260 |
| Model | Variant | AudioVAE | Model Only | Without Encode | Full Pipeline | Total Time (s) |
|---|---|---|---|---|---|---|
| voxcpm1.5 | Q4_K | mixed | 0.342 | 0.432 | 0.622 | 2.189 |
| voxcpm1.5 | Q4_K+AudioVAE-F16 | f16 | 0.336 | 0.426 | 0.596 | 2.192 |
| voxcpm1.5 | Q8_0 | mixed | 0.320 | 0.411 | 0.596 | 2.002 |
| voxcpm1.5 | Q8_0+AudioVAE-F16 | f16 | 0.308 | 0.397 | 0.559 | 2.148 |
| voxcpm1.5 | F16 | mixed | 0.352 | 0.442 | 0.648 | 1.970 |
| voxcpm1.5 | F16+AudioVAE-F16 | f16 | 0.347 | 0.438 | 0.655 | 1.885 |
| voxcpm1.5 | F32 (baseline) | original | 0.414 | 0.503 | 0.686 | 2.305 |
| voxcpm-0.5b | Q4_K | mixed | 0.401 | 0.442 | 0.550 | 2.067 |
| voxcpm-0.5b | Q4_K+AudioVAE-F16 | f16 | 0.396 | 0.437 | 0.555 | 1.953 |
| voxcpm-0.5b | Q8_0 | mixed | 0.430 | 0.470 | 0.623 | 1.644 |
| voxcpm-0.5b | Q8_0+AudioVAE-F16 | f16 | 0.417 | 0.456 | 0.595 | 1.809 |
| voxcpm-0.5b | F16 | mixed | 0.390 | 0.428 | 0.567 | 1.678 |
| voxcpm-0.5b | F16+AudioVAE-F16 | f16 | 0.392 | 0.430 | 0.565 | 1.718 |
| voxcpm-0.5b | F32 (baseline) | original | 0.500 | 0.539 | 0.680 | 1.903 |
RTF Definitions:
voxcpm1.5 Q4_K+AudioVAE-F16 leads on model-only and without-encode RTF, while voxcpm1.5 Q8_0 has the best full-pipeline RTF; voxcpm-0.5b Q4_K remains the strongest overall CPU choice.Q4_K+AudioVAE-F16 gives the best voxcpm1.5 model-only and without-encode RTF, while Q8_0 gives the best full-pipeline RTF.voxcpm-0.5b Q4_K has the best overall CPU RTF, with Q8_0+AudioVAE-F16 close behind on full-pipeline performance.voxcpm1.5 and voxcpm-0.5b show the worst CPU RTF with F32 baseline weights.3.83-15.02 on CPU to 0.55-0.69 on CUDA in this benchmark set.voxcpm1.5, Q8_0+AudioVAE-F16 gives the best RTF, while F16+AudioVAE-F16 gives the shortest total time; for voxcpm-0.5b, Q4_K gives the best full-pipeline RTF, while Q8_0 gives the shortest total time.Q4_K is not consistently the fastest on CUDA; Q8_0 and F16 are often competitive or better.F16 improves several CUDA runs, especially for voxcpm1.5 Q8_0 and voxcpm-0.5b Q8_0.| Scenario | Recommended Config |
|---|---|
| Production | voxcpm-0.5b Q4_K (477 MB, RTF 3.609) |
| Balanced accuracy | voxcpm1.5 Q8_0 (942 MB, RTF 4.291) |
| Best 1.5B offline prompt pipeline | voxcpm1.5 Q4_K+AudioVAE-F16 (647 MB, RTF 2.848 without encode) |
| Max accuracy baseline | voxcpm1.5 F32 (3392 MB, RTF 7.494) |
| Scenario | Recommended Config |
|---|---|
| Lowest full-pipeline RTF | voxcpm-0.5b Q4_K (477 MB, RTF 0.550) |
| Best 1.5B latency/RTF balance | voxcpm1.5 Q8_0+AudioVAE-F16 (984 MB, RTF 0.559) |
| Smallest CUDA-friendly 1.5B model | voxcpm1.5 Q4_K+AudioVAE-F16 (647 MB, RTF 0.596) |
| Max accuracy baseline | voxcpm1.5 F32 (3392 MB, RTF 0.686) |
CPU test environment:
logs/benchmark_summary_cpu_20260318_092142.txtCUDA test environment:
CUDA0logs/benchmark_summary_cuda_20260318_092028.txtC++
87.0%
TypeScript
5.4%
JavaScript
3.3%
Python
2.3%
Shell
1.4%