Export to ONNX
July 20, 2026 · View on GitHub
This page covers converting a trained checkpoint to an ONNX voice and confirming it works. It
is for anyone who has a .ckpt from training and wants a deployable voice.
Command
python -m phoonnx_train.export_onnx CHECKPOINT --config CONFIG [options]
CHECKPOINT is the single positional argument. There is no second positional for the
output file — the output location is set with -o/--output-dir.
| Option | Default | Description |
|---|---|---|
CHECKPOINT | required | Path to the trained .ckpt (positional) |
-c, --config PATH | required | The config.json produced by preprocess |
-o, --output-dir PATH | current dir | Directory to write the ONNX model into |
--engine NAME | vits | Architecture used for training (must match how it was trained) |
-t, --generate-tokens | off | Also write tokens.txt (needed by some engines, e.g. sherpa) |
-p, --piper | off | Also write a Piper-compatible .json |
-a, --add-phoneme-alignment | off | Expose the phoneme duration tensor as an extra ONNX output (VITS only); see Phoneme alignment |
The export is engine-aware: passing --engine uses that engine's export procedure and
metadata format. The output filenames depend on the engine — VITS writes model.onnx, while
two-graph engines write their pair (ZipVoice: text_encoder.onnx + fm_decoder.onnx;
StyleTTS2: model.onnx + style_encoder.onnx).
Example
python -m phoonnx_train.export_onnx \
train_out/runs/lightning_logs/version_0/checkpoints/epoch=999-step=250000.ckpt \
--config train_out/config.json \
--engine vits \
--output-dir exported \
--generate-tokens \
--piper
Expected output in exported/: model.onnx, plus tokens.txt and a Piper .json when
those flags are set.
--piperis only meaningful for voices withphoneme_type=espeakandalphabet=ipa, since the Piper runtime expects that phonemization.
Validating the exported voice
Load the exported model with the same config.json and synthesize a sentence:
import wave
from phoonnx.voice import TTSVoice
voice = TTSVoice.load("exported/model.onnx", "train_out/config.json")
with wave.open("check.wav", "wb") as wav_file:
voice.synthesize_wav("Testing the exported voice.", wav_file)
If check.wav plays back intelligible speech, the export is good. Common issues:
- Silence or noise — the
--engineat export time did not match how the model was trained, or the wrongconfig.jsonwas passed. invalid phonemizerat load — the config'sphoneme_type/alphabetnames a backend whose install extra is missing.- Two-stage engine sounds buzzy — it needs its separate vocoder; see Vocoders.
Ship the exported voice through the OVOS plugin or load it directly as in Usage.