ONNX export of Supertonic-3 for on-device,
browser-wasm text-to-speech. One 198 MB pack serves every supported language.
Used by Traxlate for offline dubbing and read-aloud. Weights and
architecture are Supertone's; this repo is a quantisation + packaging of their release.
⚠ q8ve means "quantise the vector estimator, NOT the vocoder"
This is the whole point of the export, and it is easy to get wrong in a way that every
cheap check misses.
arm
what was quantised
round-trip WER
q8ve (this repo)
vector estimator only
0.0172
q8
vector estimator + vocoder
0.7241
q8voc
vocoder only
5.0862 (noise)
Sample counts were byte-identical (1,422,336) across all three arms and every graph
loaded in all three. Output length, file size and a successful InferenceSession.create
tell you nothing about whether a TTS export still speaks. Only a round-trip
(synthesise → ASR → compare) separates them.
Contents
onnx/tts.json 8 KB config (sample rate, latent dims, chunking)
onnx/unicode_indexer.json 278 KB 65,536-entry codepoint table (8,321 mapped)
onnx/duration_predictor.onnx 3.7 MB
onnx/text_encoder.onnx 36.4 MB
onnx/vector_estimator.onnx 65.4 MB int8 — run once per denoising step
onnx/vocoder.onnx 101.4 MB float — DO NOT QUANTISE
voice_styles/F1.json 292 KB the single speaker
One speaker, many languages
The pack ships one voice style (F1, extracted from a 44.1 kHz source). Selecting a
language does not select a speaker — every language speaks in the same voice.
Language is carried in the text, not by an embedding: tts.json reports n_langs: 0,
and the model expects the utterance wrapped as <en>Hello there.</en>. Dropping the tag
does not raise an error; it just synthesises with the wrong accent.
Coverage is a property of the codepoint table
unicode_indexer.json maps 8,321 codepoints. Anything outside it becomes -1 — again,
silently, with no exception. Bengali (U+0980–U+09FF) has 0 of 128 codepoints
mapped, so this pack can never speak it. Persian and Urdu lose ZWNJ, U+0691 and U+06BA.
Check the table before adding a language, and gate on a round-trip measurement per
language rather than on one English clip.
Usage (onnxruntime-web)
Four graphs, driven by an iterative denoising loop:
vector_estimator → run once per step, feeding its output back as noisy_latent
vocoder → waveform
Four steps is what the WER figure above was measured at. Fewer steps degrades audibly
before it saves meaningful time.
WASM only. Supertonic's ConvNeXt depthwise-conv is fragile on GPU execution providers
(it breaks ORT-GPU on Pascal and onnxruntime-web WebGPU on some devices). CPU-wasm measured
RTF 0.296 — comfortably faster than realtime — so there is nothing to gain and a crash to
lose.
Per-language round-trip CER (CER, not WER — word segmentation is meaningless for ja/ko)
was measured over 27 languages × 2 clips before any language was shipped.