File size: 7,334 Bytes
23c283a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
---
license: apache-2.0
language:
  - as
  - bn
  - en
  - gu
  - hi
  - kn
  - ml
  - mr
  - or
  - pa
  - ta
  - te
library_name: mlx
pipeline_tag: text-to-speech
base_model: maya-research/maya2-native
tags:
  - mlx
  - apple-silicon
  - text-to-speech
  - tts
  - indic
  - multilingual
  - mimi
  - 8-bit
---

# Maya 2 Native for MLX (dynamic 8-bit)

An Apple Silicon (MLX) port of [Maya 2 Native](https://huggingface.co/maya-research/maya2-native) by Maya Research:
streaming text-to-speech for 11 Indic languages and English, with 20 built-in voices. It runs with no PyTorch and no
CUDA, faster than real time on an M5.

- **Ported line by line** from the [official code](https://github.com/MayaResearch/maya2-native) (commit
  `c6b3768`): the backbone, the depth decoder, the Mimi decoder, the sampler with its stop rules and guards, the
  official random-number stream, text splitting, prompts and the tokenizer.
- **Proven against the official model** before quantizing: at the official 16-bit precision the port gives the same
  codes, stops and audio (within one int16 step) as the official code on every test request (strict gates, fp32),
  and the same accuracy at its own precision (production gates).
- **Dynamic 8-bit weights** (`models/maya2-8bit`, in the spirit of Unsloth's dynamic quants): every tensor's
  sensitivity was measured against the official model; the outliers and the sensitive depth decoder stay 16-bit,
  the rest is 8-bit. 3.57 GB, with a sampling shift about 1.2× the official 16-bit model's own rounding noise in all
  12 languages. (A plain 8-bit set, every weight 8-bit, was measured too and left out: up to 7× the official noise.)

Independent port; not an official Maya Research release. See `NOTICE.md`.

## Quickstart

Requirements: an Apple Silicon Mac, Python 3.11, about 6 GB of free memory.

```bash
hf download zero0303/maya2-mlx-dynamic-8bit --local-dir maya2-mlx
cd maya2-mlx
uv venv --python 3.11 .venv
VIRTUAL_ENV=$PWD/.venv uv pip install "mlx==0.32.4" numpy "tokenizers==0.22.2"
.venv/bin/python -I speak.py "A heap keeps its smallest item at the top." --voice Malini --seed 7 -o heap.wav
.venv/bin/python -I speak.py --voices
```

From Python:

```python
import sys; sys.path.insert(0, "maya2-mlx")
from maya2_mlx import Maya2

tts = Maya2()                                   # models/maya2-8bit
wav = tts.generate("नमस्ते, आप कैसे हैं?", lang="hi", voice="Vaidehi", seed=11)    # float32, 24 kHz, in [-1, 1]
for pcm in tts.stream("Long text ...", lang="en", voice="Anirban"):              # int16 chunks as they are made
    ...
```

`generate` / `stream` follow the official `Maya3TTS` API: `lang`, `voice` (a built-in name, case-insensitive, or
`None` for the plain voice), `seed`, `temperature`, `top_k`, `top_p`, `repetition_penalty` (the codebook-0 sampler),
`max_frames`, `normalize` (the bundled text normaliser: digits, currency, dates, URLs). Long text is split into
~20-second pieces with 0.15 s gaps, as in the official engine. The same seed gives the same audio.

## Voices

| Voice | | | Description | Trained languages |
|---|---|---|---|---|
| Ahana | female | young | bright, youthful | 11 |
| Vaidehi | female | adult | calm, gentle | 11 |
| Malini | female | mature | steady narrator | 11 |
| Charvi | female | young | energetic, upbeat | 11 |
| Jahnavi | female | adult | warm, friendly | 10 (not pa) |
| Anirban | male | adult | steady narrator | 11 |
| Nakul | male | young | bright, youthful | 11 |
| Vasant | male | mature | steady narrator | 10 (not pa) |
| Siddhant | male | adult | clear, professional | 11 |
| Satvik | male | young | warm, friendly | 11 |
| Abhay, Akshat, Shaunak | male | adult / young | natural conversational | en, hi |
| Nivedita, Tanushree | female | adult | natural conversational | en, hi |
| Ishwari, Vrinda | female | adult / young | natural conversational | hi |
| Ritvik | male | adult | natural conversational | hi |
| Sreekar | male | adult | natural conversational | en, hi, te |
| Kayal | female | adult | natural conversational | en, ta |

"11" = bn, en, gu, hi, kn, ml, mr, or, pa, ta, te. Other languages work cross-lingually (Assamese for every voice).

## Speed and quality

Measured on an M5 (24 GB), the same 23.4 s English paragraph, and the parity gates against the official model
(plain 8-bit and 16-bit for comparison; only the dynamic 8-bit is in this repository):

| | **Dynamic 8-bit** (this repository) | Plain 8-bit | 16-bit |
|---|---|---|---|
| Download | 3.57 GB | 2.93 GB | 5.24 GB |
| Peak memory | 5.8 GB | 4.2 GB | 8.2 GB |
| Time for 23.4 s of speech | 18.4 s (1.27× real time) | 15.5 s (1.5×) | 20.6 s (1.14×) |
| Sampling shift vs exact, 12 languages (official 16-bit noise = 1×) | ~1.2× (0.6–2×) | ~3.5× (1.5–7×) | 1× |
| Depth decoder (fine sound detail) | exact, as the official | 1.6–2.8% error; decisions change beyond near-ties | exact |
| Parity gates vs the official model | 101/101 | 86/101 | 101/101 |

## Files

| File (`models/maya2-8bit/`) | Size | Contents |
|---|---|---|
| `backbone-main.safetensors` | 460 MB | token embeddings (8-bit), final norm, cb0 head, RoPE tables |
| `backbone-layers-00/07/14/21.safetensors` | 4 × 396-407 MB | 28 Qwen3-shaped layers, linears 8-bit (layers 2 and 27 down-projection kept 16-bit) |
| `depth.safetensors` | 1.10 GB (16-bit) | depth decoder |
| `audio_in.safetensors` | 151 MB | feedback table, 8-bit |
| `mimi.safetensors` | 230 MB | Kyutai Mimi decoder, fp32 |
| `anchor.safetensors` | 2.3 MB | speaker anchor, bf16 |
| `tokenizer.json`, `voices.json`, `meta.json`, `quant.json` | 16 MB | tokenizer, voices, source checksums, quantization recipe |
| **total** | **3.57 GB** | |

Code: `maya2_mlx/` (the port), `maya3/` and `configs/` (official files, unchanged), `speak.py`. The parity tests
against the official model, the export and quantization scripts and the 16-bit MLX export are not part of this
repository; their results are summarised below.

## How it was checked

| | Result |
|---|---|
| Tokenizer | 546/546 prompts identical to the official (12 languages × 13 voices, Devanagari edge cases) |
| Strict gates (fp32, CPU and GPU) | 92/92 each: identical sampler decisions and codes on every frame, same free-running requests (37 s / 3 pieces included) |
| Production gates (16-bit) | 101/101: as accurate as the official bf16 (error ratio 1.02); depth flips only at near-ties, as the official's own fp32-vs-fp16 |
| Dynamic 8-bit | 101/101 against the official model; sampling shift 1.2× the 16-bit floor |
| Reviews | two independent code reviews against the official source; one hidden issue found and fixed (the official engine builds RoPE from bf16 frequencies) |

## Not included

Voice cloning (ECAPA speaker encoder, Mimi encoder), emotion-tag evaluation, multi-request batching and the HTTP
server. One request at a time.

## Licenses and credit

Maya 2 Native weights and code © Maya Research, Apache-2.0 (`LICENSE`). Kyutai Mimi © Kyutai, CC BY 4.0 (decoder
only, re-laid out for MLX). Qwen3 architecture, Apache-2.0. Details and the original citation: `NOTICE.md`.
Use the voices responsibly: disclose synthetic speech, no impersonation (see the
[original model card](https://huggingface.co/maya-research/maya2-native#intended-use-and-responsible-deployment)).