ONNX conversion of Prince-1/OmniVoice — a zero-shot
text-to-speech model supporting 600+ languages — via Olive
and onnxruntime-genai ModelBuilder.
OmniVoice is not a vision-language model. It is a TTS model: a Qwen3-0.6B backbone driving an
8-codebook audio codec (Higgs Audio V2 Tokenizer) through a 32-step non-autoregressive unmasking
loop. All conversion configuration is defined in Python (optimize.py) — there are no external
Olive JSON files.
onnxruntime-genai's valid precision × execution-provider combos are FP32/INT4 on CPU and
FP16/INT4 on CUDA — there is no FP16 LLM on CPU. Olive's ModelBuilder pass therefore can't
emit a CPU fp16 LLM, so optimize.py calls genai create_modeldirectly and builds the LLM
int4 on CPU (fp16 on GPU). The audio sub-models still go through Olive. The genai LLM declares
only inputs_embeds + attention_mask (+ KV cache) and computes positions internally — no
position_ids input.
Precision profiles
--device
audio sub-models
LLM
output dir
cpu
int4 (block-wise RTN, block 128)
int4
<output>
cpu_fp16
fp16
int4 (no fp16-CPU in genai)
<output>
gpu
fp16
fp16 (CUDA EP)
<output>
Higgs is exported fp16 (default) or fp32 via --higgs-precision — never int4 (too lossy for the DAC
codec). It is precision-shared: an int4 backbone still uses the fp16/fp32 audio_tokenizer/.
Built sizes (verified)
file
fp16 (cpu_fp16)
int4 (cpu)
audio_embeddings_encoder.onnx(.data)
327 MB
87 MB
audio_heads_decoder.onnx
16.8 MB
4.5 MB
llm_decoder.onnx(.data)
296 MB (int4)
296 MB (int4)
Higgs audio_tokenizer/ (fp16)
~370 MB
(shared)
Prerequisites
bash
1pip install -r requirements.txt # olive-ai, onnxruntime, onnxruntime-genai, transformers 5.x2pip install omnivoice # registers the base OmniVoice architecture for loading
omnivoice is only needed at build time (to load the source checkpoint); inference needs only
onnxruntime + numpy + soundfile. In this repo's env the build is run isolated as
uv run --with omnivoice python optimize.py … to keep the base environment clean.
optimize.py (1) saves OmniVoice's internal Qwen3 as a standalone Qwen3ForCausalLM dir, (2) builds
the two audio sub-models via inline Olive configs and the LLM via genai create_model, (3) copies
the tokenizer + chat_template.jinja, and (4) writes omnivoice_manifest.json. All model_config.json
paths are relativized to bare basenames so the folder is portable.
Inference (CPU)
bash
1# fp16 backbone2python inference.py --model_dir onnx --higgs_dir onnx/audio_tokenizer \3 --text "Hello from OmniVoice." --output out.wav
45# int4 backbone (shares the same Higgs tokenizer — int4 dir has no audio_tokenizer/ of its own)6python inference.py --model_dir onnx/int4 --higgs_dir onnx/audio_tokenizer \7 --text "Hello from OmniVoice." --output out_int4.wav
--num_audio_tokens sets output length in frames (≈ frames × 0.04 s); --num_steps the unmasking
steps (the loop fills ⌈remaining/remaining_steps⌉ frames per step so every frame is decoded). Voice
cloning: add --ref_audio ref.wav --ref_text "…" (uses the Higgs encoders).