Downloads · 30 days
0
christopherthompson81/omnivoice-ipa-onnx
omnivoice-ipa-onnx is a text-to-speech model from christopherthompson81. Use it when you need text read aloud. It is set up for onnx. The card lists the license as cc-by-nc-4.0.
An ONNX conversion of k2-fsa/OmniVoice (a non-autoregressive diffusion-LM TTS), plus a small IPA fine-tune diff that teaches the model to accept IPA phoneme strings (from vernacula-phonemizer) as text input — so the p…
Downloads · 30 days
0
Access
Public
Updated Sep 8, 2026
Repo size
4.3 GB
Likes
0
Public
Click a slice to open those files.
.data2.9 GB · 79%
From the Hugging Face model README
An ONNX conversion of k2-fsa/OmniVoice (a
non-autoregressive diffusion-LM TTS), plus a small IPA fine-tune diff that teaches the model to
accept IPA phoneme strings (from vernacula-phonemizer)
as text input — so the phonemizer, not the model, owns the linguistic G2P: dictionary + neural G2P,
stress, pitch accent, and text normalization (numbers, %, currency, units spoken in-language) all
happen before the model sees a token.
vernacula.netlify.app runs this model entirely in your browser — 193 languages, no upload, no server inference. It downloads the quantized build below (472 MB, cached after the first load) and does the phonemization locally too.
The same pipeline also ships as a desktop app and a command-line renderer in vernacula. The desktop version is runs at 2.5x realtime on a 3090.
| File | Size | What |
|---|---|---|
omnivoice_transformer.onnx (+.onnx.data) | 2.45 GB | base transformer (embeds + Qwen3-0.6B + audio heads), fp32 |
higgs_encoder.onnx | 654 MB | Higgs codec encoder (24 kHz audio → codes) |
higgs_decoder.onnx | 86 MB | Higgs codec decoder (codes → 24 kHz audio) |
omnivoice_transformer_ipa.int4.onnx (+.onnx.data) | 472 MB | the fine-tuned transformer, merged and quantized for browsers — no base or diff needed |
tokenizer.json | 11 MB | the Qwen3 tokenizer, for consumers that synthesise text |
ipa_diff.onnx | 31 MB | the IPA fine-tune, as a reconstruction diff over the base transformer (currently the v7 extraction) |
voices/voices.jsonc + voices/voice-codes.json | 3 MB | the stored-voice library: 530 reference voices covering the phonemizer's languages — per voice the codec codes of a short clip, the IPA it was transcribed with, and its source — so cloning needs neither the 654 MB encoder nor any audio |
manifest.json | per-file MD5s, for the desktop app's update check |
Every language gets a native voice where a usable clip exists, else a donor from a related
language; default marks the one a consumer should start from, and source names the exact
clip so a poor exemplar can be traced and replaced. The web demo and the desktop app read the
same two files, so all three renderers share one voice per language. How the clips were chosen,
and what still lacks one, is in
docs/voice_sourcing.md.
Native speakers that can help align the voices audio and reference IPA would be appreciated.
The transformer is the base (un-fine-tuned) graph; the encoder/decoder are the codec, unchanged by the fine-tune. The IPA fine-tune is distributed as a 31 MB diff rather than a second 2.45 GB merged graph.
The diff holds a LoRA plus absolute replacement embedding rows, so it is only meaningful against the exact base it was extracted from. Applied to any other weights it produces a plausible-looking model that is quietly wrong — the perturbation is the same order as the fine-tune itself — and nothing in the diff can detect this: the per-row delta distributions for a right and a wrong base overlap. Check the fingerprint:
sha256sum omnivoice_transformer.onnx.data
# 2ea0980e184bbf8457048fbb3ed2a01f8f8c3816a8ee9fbff3ce0886c1aeeb4a
The diff carries, per Linear (q/k/v/o/gate/up/down x 28 layers = 196 modules), the LoRA factors
A (r=16, in) and B (out, r) with lora_scale = alpha/r = 2.0 in the model metadata, plus the
changed embed_tokens rows as embed_rows (fp16) and embed_idx (int32).
Recommended — rewrite the graph, keeping the LoRA factored. Leave the base weights alone and add nodes:
MatMul(x, W) -> Y becomes
MatMul(x, W) -> Y_base ; MatMul(x, A^T) -> t ; MatMul(t, scale*B^T) -> d ; Add(Y_base, d) -> Y
with a sparse additive correction for the embedding (a compact (changed+1, hidden) delta table
with a zero row 0 and a (vocab,) int32 map, as two Gathers and an Add). Insert each chain at the
original node's position, not at the end of the graph, or the Add lands after its own consumers.
Because no weight is replaced, the runtime loads the base from the untouched .onnx.data and this
works on every execution provider. Measured against a full PyTorch merge: argmax agreement
100.000%, max|dlogit| 1.1e-4 (CPU) / 6.1e-5 (CUDA).
Alternative — fold into the weights (W += ((B@A)*scale)^T, overwrite the changed embed rows).
Also exact, but note that ⚠ if you feed the folded weights back through
SessionOptions.AddInitializer, ONNX Runtime will silently ignore them on any non-CPU provider —
a user-supplied initializer must be a CPU tensor, so when the session is planned on CUDA every one
is rejected ("Cannot use user supplied initializer ... planned memory location device is
different") and the base graph is served instead. The output is then bit-identical to using no diff
at all, which for IPA input is noise. If you fold, write the merged model out and load it from
disk.
Reference implementations: apply_diff.py (Python, fold) and OmniVoiceDiff (C#, graph rewrite)
in vernacula.
Text -> IPA -> audio, with the phonemizer owning all G2P. The model is conditioned
language-agnostically (<|lang_start|>None<|lang_end|>); the IPA stream carries everything.
⚠ Short input needs a reference voice. The fine-tune corpus is FLEURS read prose — median 12 s, only 0.21% under 3 s — so under ~5 s the model is out of distribution and can emit noise rather than degrade gracefully. Supplying a reference clip for voice cloning fixes it, as does lengthening the text. Generation is greedy (temperature 0) and therefore deterministic: re-running reproduces a failure byte-for-byte.
⚠ This repo is licensed PER FILE, and the HuggingFace tag names only the strictest part. The files come from two different upstreams with different terms, and treating them alike would either over-restrict the codec or under-restrict the transformer.
| file | origin | licence |
|---|---|---|
omnivoice_transformer.onnx(.data), ipa_diff.onnx, omnivoice_transformer_ipa.int4.onnx(.data) | k2-fsa/OmniVoice pre-trained weights | CC-BY-NC-4.0 |
higgs_encoder.onnx, higgs_decoder.onnx | bosonai/higgs-audio-v2-tokenizer | Boson Higgs Audio 2 Community License (commercial use permitted below 100k annual active users) |
tokenizer.json | the Qwen3 tokenizer | Apache-2.0 |
voices/voices.jsonc, voices/voice-codes.json | codec codes + IPA of short reference clips from public speech corpora | per clip, as the source field says: FLEURS, Omnilingual ASR, Vaani and most others CC-BY-4.0; Common Voice CC0; OpenSLR 83/158/44 CC-BY-SA-4.0; LibriVox public domain — see docs/voice_sourcing.md for the full table |