MioTTS-0.6B, int8 for the browser
Aratako/MioTTS-0.6B quantized to per-row int8 so it can run in a web browser on WebGPU, as part of voxshot.
This is a repackaging, not a new model. Every weight comes from the Apache-2.0 checkpoint above; nothing was trained, fine-tuned or distilled. Please cite and credit the original.
| Source checkpoint | 1,217,825,224 B (bf16) |
| This one | 611,153,856 B (int8 + f32 scales) |
Why this exists
A browser cannot afford the bf16 checkpoint, and the op library this runs on (web-xpu-ops) has exactly one quantized kernel: a fused W8A32 GEMV over per-row absmax int8. So that is the format. There is no f16 path โ no shader-f16 kernels exist upstream.
Files
| file | bytes | contents |
|---|---|---|
manifest.json |
68,159 | per-tensor offsets, shapes, config, provenance |
weights.codes.bin |
608,829,440 | int8 codes, one byte each, tensors concatenated |
weights.scales.bin |
2,034,176 | f32, one scale per output row |
weights.norms.bin |
290,816 | f32 norm vectors, unquantized |
manifest.json is the index: every tensor entry carries rows, cols and a
byte offset into the file it lives in. Nothing else is needed to read these.
The quantization
Per-row absmax symmetric int8. For each output row, scale = max|w| / 127 and
code = round(w / scale) clamped to [-127, 127]; an all-zero row gets
scale = 1. Rounding is half-up, matched bit-for-bit against the consumer's
own quantize op on real rows of this checkpoint.
Quantized: q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj,
down_proj per layer, and embed_tokens once โ the embeddings are tied, so
that one matrix serves as both the lookup table and the output projection.
Left in f32: the layer norms and the per-head q/k-norm gains, 291 KB in total,
where quantization would buy nothing and cost accuracy.
What it costs, measured
Against the f32 original, stage by stage:
- element error at the theoretical bound, ~`scale/2` โ 0.0039 of each row's peak
- prompt logits within 4.8e-2 peak-relative (Japanese) and 1.2e-2 (English), with the argmax unchanged at the prompt boundary in both
- greedy generation diverges from f32 at step 6 on a Japanese test sentence: an adjacent-codebook near-tie flips, and the trajectory then differs while remaining well-formed โ 87 speech tokens and a clean EOS against f32's 83.
That last point matters if you plan to compare outputs: int8 does not reproduce the f32 token sequence, and it is not supposed to. Compare against an int8 reference, or compare the audio.
RoPE channels are permuted
q_proj and k_proj rows, and the q_norm / k_norm gains, are
relabeled from Hugging Face's rotate-half pairing (j, j+64) to the
adjacent-pair pairing (2i, 2i+1) that the consumer's RoPE kernel implements.
Per head: j โ 2j for j < 64, else j โ 2(j-64)+1.
manifest.json records this as "ropePermuted": true. The unpermuted gains
are also stored, as qNormRaw / kNormRaw, so the original order is
recoverable.
If you feed these weights to a stock Hugging Face implementation without undoing the permutation, you will get noise. They are shaped for one consumer.
Provenance
Produced by spike/miotts/convert_weights.py from:
Aratako/MioTTS-0.6B model.safetensors
1,217,825,224 bytes
sha256 d0f85e5d9799c1589d7ba7c1c7830a7e2b6e4424ed07da2f76a56bc2ed7dc449
The converter re-hashes that file and aborts on a mismatch, and manifest.json
records the digest, so these weights and the checkpoint they came from cannot
drift apart unnoticed.
Architecture, for reference
Qwen3, 28 layers, hidden 1024, 16 query heads / 8 KV heads, head dim 128, FFN
3072 SwiGLU, RMSNorm eps 1e-6, RoPE theta 1e6, tied embeddings, vocab 164,480.
Speech tokens are <|s_n|> = id 151669 + n for n in 0..12799, which index
Aratako/MioCodec-25Hz-24kHz
at 25 tokens per second.
License and attribution
Apache-2.0, inherited from the source checkpoint.
- Model: Aratako/MioTTS-0.6B by Chihiro Arata
- Codec it pairs with: Aratako/MioCodec-25Hz-24kHz (MIT)
@misc{miotts,
author = {Chihiro Arata},
title = {MioTTS: Lightweight and Fast LLM-based Text-to-Speech},
year = {2026},
publisher = {Hugging Face},
journal = {Hugging Face repository},
howpublished = {\url{https://huggingface.co/collections/Aratako/miotts}}
}