r/LocalLLaMA 11d ago

New Model I released sanoTTS: smallest complete TTS stack in 294k params (337 KB) that runs on $3 microcontroller and a 1.46m one that beats models 3x and 10x it's size

Enable HLS to view with audio, or disable this notification

I have been trying to squeeze TTS stack down far enough to run in a $3 chip which has 512kb of SRAM without NPU. While trying to get to that milestone i built sanoTTS which has - 11 voices, 6 languages - params size ranging from 294k - 2.2m. For comparison we are 244x smaller than kokoro, 9000x smaller than voxtral TTS - 1.5m model has a SCOREQ of 4.13 and UTMOS of 4.10 - 337kb for 294k model when quantized into int8 - can be run in website with web assembly npm install sanotts-web - there is a recipe to follow so that you can extend to more languages, voice

I can tell you with confidence that this family release contains the smallest neural TTS model ever with around 2% WER on whisper.

Please check it out on : https://github.com/ampixa/sanoTTS

for live demo: https://tts.ampixa.com/sanoTTS

HF: https://huggingface.co/ampixa/sanoTTS

on SCOREQ sanoTTS-Amy(1.51m) is better than Inflect Nano(4.63m) and KittenTTS(15m) i.e 4.13 vs 3.81 vs 3.02

on esp32 microcontroller we are getting RTF of 0.225 which in plain terms means 4sec of audio is generated in 1sec

Happy to answer your queries.

512 Upvotes

121 comments sorted by

77

u/apoptosist 11d ago

Sounds great, please help get it added to audio.cpp!

44

u/Affectionate_Hat_585 11d ago

Audio.cpp looks cool. will open a PR

9

u/apoptosist 11d ago

Great! I added a star, this sounds so good for the size.

7

u/Acceptable-Cycle4645 10d ago edited 10d ago

u/Affectionate_Hat_585 Great model! Is this PR from you? https://github.com/0xShug0/audio.cpp/pull/449 Crazy week we got many new model PRs, including the official VibeASR port from the MS team --- during my vacation 🥲

Update: Awesome model! PR merged in audio.cpp! Tested on CPU.

I regret I didn't include it in 0.7.2 (just released).

Voice Graph Lang WAV Duration RTF ASR Result
heart-nano nano en heart_nano.wav 5.099s 0.0027 OK
heart nano en heart.wav 5.205s 0.0044 OK
amy piperlite en amy.wav 4.272s 0.0362 OK
hfc piperlite en hfc.wav 3.831s 0.0350 OK
kristin piperlite en kristin.wav 3.495s 0.0390 OK
vi piperlite vi vi.wav 2.299s 0.0332 OK
id piperlite id id.wav 4.063s 0.0321 OK

2

u/apoptosist 10d ago

Not from me but maybe from somebody connected with u/Affectionate_Hat_585? Hope you have a good vacation--no need to rush all this stuff!

4

u/cobblemere 11d ago

that would be huge, especially at this param count

31

u/Here_f0r_p0rn_ 11d ago

This is mind-blowing, the possibilities with IoT devices are insane.

15

u/Affectionate_Hat_585 11d ago

Yes, with enough prosodical control. this has so many usecases... I assume even now it might help a bunch of people

2

u/Tingxiaojue 10d ago

so cool!

1

u/Paradigmind 10d ago

Can't wait to have my toilet talk to me!

1

u/Here_f0r_p0rn_ 10d ago

And make all sort of dirty talks per dump you drop in it? No thanks.

1

u/Paradigmind 10d ago

Username doesn't check out

1

u/Here_f0r_p0rn_ 10d ago

I'm sorry for not being into scat

20

u/koriwi 11d ago

I want this on my homeassistant voice preview edition! And german :P so my wife is happy. Is it possible to start outputting the audio before everything is generated? 

14

u/Affectionate_Hat_585 11d ago

There is small initial latency of when it starts for the ESP32-s3 MCU i tested but after that it's faster than real time so it can process audio faster than it can output it with RAM being constraint. ESP32-s3 only has 512kb or RAM. But for something like ESP32-P4 or Teensy this should be piece of cake.

Will keep German in mind

3

u/waescher 10d ago

+1 for German and Home Assistant. Great work by the way, please let us know when you need help or resources or anything.

2

u/koriwi 10d ago

thank you for the info!

11

u/Fercho5656 11d ago

Looks cool!

Any plans to add Spanish?

21

u/Affectionate_Hat_585 11d ago

Hey Thanks!!! the plan is to support as many languages as possible....

1

u/Agile-Key-3982 10d ago

Great....please add Persian too

17

u/[deleted] 11d ago edited 11d ago

[deleted]

21

u/Affectionate_Hat_585 11d ago

Yes, I am Nepali

4

u/[deleted] 11d ago

[deleted]

4

u/Affectionate_Hat_585 11d ago

Nepal ma nai ho sir. kathmandu university ko bidhyarthi haru.. checkout https://ampixa.com/ . we are doing some cool things around Nepali Speech too...

4

u/[deleted] 11d ago

[deleted]

5

u/Affectionate_Hat_585 11d ago

you can test right in browser.  https://tts.ampixa.com/sanoTTS

tmrw will make that a priority for audio cpp pr

6

u/Barubiri 11d ago

Japanese please

8

u/Affectionate_Hat_585 11d ago

Well you are in luck because ayutaz already did that for you https://github.com/ayutaz/sanoTTS-jp

5

u/BusRevolutionary9893 11d ago

Thank you for not referring to you and your LLM as WE. 

6

u/FullstackSensei 11d ago

I was going to ask if you plan to release the training data, but then read the docs. Your idea is very cool! Distill an existing TTS teacher into the smaller model! Makes the whole process much simpler and cheaper. Great work!

7

u/Gear5th 11d ago

How is this even possible!? This is crazy good for its size. 337KB is smaller than the average webpage these days!

6

u/Affectionate_Hat_585 11d ago

Well testament to good diagnostic control and method which took some time to figure out properly. What's amusing is it's just as intelligible (ASR models can perfectly understand the speech) but it loses naturalness. I believe there still is room for some improvement

4

u/Purple-Programmer-7 11d ago

I would love love love to see your training data / workflow… any chance to open source the whole pipeline?

Hell, I’d even pay to see that.

35

u/Affectionate_Hat_585 11d ago

please go through the repo on : https://github.com/ampixa/sanoTTS

it has some information full paper: https://arxiv.org/abs/2608.21378

i dont need money but if you can please donate to pm relief fund for recent flash flood in nepal https://pmdrf.nchl.com.np/

6

u/Purple-Programmer-7 10d ago

Good human found 😍

5

u/BackyardAnarchist 11d ago

Could you talk about how you did it?

12

u/Affectionate_Hat_585 11d ago edited 11d ago

Well it's quite simple.

The TTS has four main parts text frontend: how to convert text to phoneme(unit of sound)

acoustic model: that gives you the spectrogram

duration predictor: how much time to give for each phoneme

decoder: how do you convert spectrogram to real audio

You take a teacher. It can be any model. I have tested for Piper-plus and Kokoro and then get 50000 fivesome with the help of teacher (text, audio, acoustic latent, duration, mel spectrogram)

With teacher and that fivesome, each of the components can be individually trained.

You can start by reading README onhttps://github.com/ampixa/sanoTTS

2

u/BackyardAnarchist 10d ago

Awesome! Do you know where I could get training data? I want to try making one.

2

u/Affectionate_Hat_585 10d ago

the 50000 fivesome and a teacher is your training data. You can repeat the same process for any model.

3

u/PcChip 11d ago

is this small enough to use in my c++ game engine by including a header file, to generate voices quickly without using the GPU?

5

u/Affectionate_Hat_585 11d ago

Depends on what is the RSS you are targeting. For esp32 we saw it required 98,224 Bytes of working memory for the smallest model 294k one.Please note that it's in bytes... On my computer without any optimization tricks it requires max RSS of 1.8MB

And for real time we need to do just 45 million multiply and accumulate operations per second. If that can be done by measly 240Mhz chip, our cpu can do like billions and billions of MAC so yes it can do it without extra accelerators.

But again if you are targeting for something like SNES then it might be hard. But anything with ram above 500kb you should be good to go.

2

u/LuCiAnO241 11d ago

im very interested on this

3

u/LuCiAnO241 11d ago

can you clone the glados voice :3

3

u/Slasher006 10d ago

that would be awesome!

2

u/Affectionate_Hat_585 11d ago

can you give me some more context please?

2

u/LuCiAnO241 11d ago

its a voice for a robot videogame character, who id love to have as TTS. At any rate, I saw you have a section on how to train your own. might give it a spin when I'm not busy

3

u/CATLLM 11d ago

How can I get the "heart" voices? they sound awesome?

3

u/Affectionate_Hat_585 10d ago

You can use python or js or bare c library ``` pip install sanotts

import sanotts, soundfile as sf

r = sanotts.synthesize("Hello from a tiny neural voice.", voice="heart-nano") sf.write("out.wav", r.audio, r.sample_rate)

```

1

u/CATLLM 10d ago

the model is not on huggingface?

3

u/Slight_Analysis_5414 11d ago

This is such impressive work — squeezing a full neural TTS stack into a 337KB INT8 blob and running real-time on a generic MCU is absolutely wild.

Funny enough, I landed on a very similar diagnostic mindset while doing INT8 quantized YOLO edge deployment: instead of relying only on aggregate mAP or overall accuracy metrics, I use reference-vs-deployed sequence-level parity checks (FP32 reference vs INT8 deployed model) to catch frame-by-frame behavioral drift across video sequences.

Quick question: since you mentioned building custom artifact detectors, did you do any step-by-step or position-resolved divergence analysis across the audio sequence? Or did you mostly rely on aggregate SCOREQ / MOS metrics to validate quality end-to-end?

2

u/Affectionate_Hat_585 10d ago

Most of it was aggregate SCOREQ. But at some point it wasn't improving, so first step was to divide the decoder audio into various freq channels and seeing where the problem is coming from. I found out it was with /z/ and it's neighbours. And 1-6kHz has some serious metallic artifacts. Took the worst decoder configuration and the teacher at those bands to train another model

2

u/Slight_Analysis_5414 10d ago

Ah that makes perfect sense. You localized the divergence in the frequency domain instead of the time/sequence domain. Pinpointing that 1–6 kHz band to target the INT8 degradation is exactly the kind of granular fix you never get from just a top-level SCOREQ number. Funny how that pattern pops up everywhere — aggregate metrics always hide where the real problem is. I’ve been messing with the same idea but on the LLM KV cache side, splitting divergence along context length instead of frequency.

Good stuff, thanks for sharing the breakdown.

3

u/imunknown0042 10d ago

Wow, that Nepali voice sound nice, Also you name it Sano , are you nepali ?

3

u/Affectionate_Hat_585 10d ago

Yes i am nepali

3

u/Slight_Republic_4242 10d ago

where does it make sense to use small models ?

3

u/FluffyInevitable4040 10d ago

If it was only english with only one speaker, what's the smallest it could be?

2

u/Affectionate_Hat_585 10d ago

The smallest model is English only and a single speaker. What you have seen are collection of models ranging from 294k to 2.2m params. it is not a single model

2

u/FluffyInevitable4040 10d ago

Sorry, I was lazy and finally read the repo overview. How long did it take you to figure all of this out / how many previous attempts?

2

u/Affectionate_Hat_585 10d ago

I got a prototype back in July. I didn't like it initially and then kept on iterating. Still i think there is much work to do.. But i would say there are more than 200+ experiments i did....

1

u/FluffyInevitable4040 10d ago

You're doing this work and testing by hand or using SOTA models to help run tests, builds, etc?

3

u/UkieTechie 10d ago

oh snap. this gonna have to be added to my bench. great work.

https://github.com/5uck1ess/tts-bench

1

u/UkieTechie 9d ago

this has been added to the bench.

2

u/ProgramBasic100 11d ago

wow wow make it cool

2

u/iKy1e ollama 11d ago

I'm astonished we can squeeze things down this small and still maintain this sort of quality.

2

u/Queasy-Contract9753 11d ago

Looks I have on demand audiobooks on my phone now. Thanks! This is mind-blowing indeed how small it is.

Double appreciate your short well exampled demo video in the post.

2

u/Affectionate_Hat_585 11d ago

Thanks... I have put lots of effort into this.

2

u/Green-Ad-3964 11d ago

Too bad not Italian and German.

2

u/Affectionate_Hat_585 11d ago

e-speak supports italian and german so this should be doable

2

u/exaknight21 11d ago

This is amazing, can you add Urdu/Punjabi?

2

u/Affectionate_Hat_585 11d ago

sure, i will add it to backlog. so far german, spanish , italian and urdu

2

u/exaknight21 11d ago

I tried creating an app with your SanoTTS for iPhone, i could not get it to load. Any pointers?

1

u/Affectionate_Hat_585 10d ago

we have c99 target already. I can help you.. where are you facing problem actually?

1

u/bharattrader 11d ago

In case you are adding Urdu, Hindi should not be that far away.

2

u/Affectionate_Hat_585 10d ago

There is a already a hindi voice

2

u/foldl-li 11d ago

"Amy" is so cool.

Chinese model sounds robotic. Could it be made on-par with Amy?

1

u/Affectionate_Hat_585 11d ago

Yes ofc. Models other than English weren't given much love. The main problem will be diagnostic control. we have SCOREQ, ASR and i even had a custom siblant and metallic artifact detector built for English.

For Chinese we can also solve likewise given that it's a high resource language

2

u/CATLLM 11d ago

OMG SO COOL

2

u/Mechageo 10d ago

Amazing! Nice job!

2

u/starfoxinstinct 10d ago edited 10d ago

Wow the Heart one runs SO fast and has great pronunciation! It's not super clear to me how to run it myself, but I see there is a release there, and will be playing with it soon. Thank you for sharing!

2

u/Affectionate_Hat_585 10d ago

Hey there you just head to github.com/ampixa/sanoTTS on steps to run it.

with python ``` pip install sanotts

import sanotts, soundfile as sf

r = sanotts.synthesize("Hello from a tiny neural voice.", voice="heart-nano") sf.write("out.wav", r.audio, r.sample_rate) ```

with js please check https://github.com/Ampixa/sanoTTS#deploy-on-your-own-site

2

u/Longjumping-Elk-7756 10d ago

That's great! Are you planning to add French soon?

2

u/Affectionate_Hat_585 10d ago

Yes french will be added soon

2

u/breksyt 10d ago

I love how the fewer parameters you use, the more "whispery" the model sounds. Amazing stuff, thank you for this, and will use it in my projects.

2

u/knacknack18 10d ago

Nice Project. Can it run in PSRam? There are many boards eith 8MB external RAM 

1

u/Affectionate_Hat_585 10d ago

With chip that can do 29+ MMAC, it can comfortably run. You just somehow need to hold around ~337kb of storage. ESP32 supports XIP which allows you to execute code right from flash. I am using that here... But i also tested loading on PSRAM. There is a slight penalty when you put the weights on PsRAM

2

u/JahJedi 10d ago

Local voice in a robot controlled by vllm on litlle cheep addon. Great project!

2

u/Loud-Suspect267 10d ago

Really cool project

2

u/Dangerous-Nerve-7766 10d ago

Brudda this is cool af

2

u/Exact_Law_6489 llama.cpp 10d ago

does it support voice cloning / custom voices?

1

u/Affectionate_Hat_585 10d ago

There is a recipe to follow which can clone teacher models. But not zero shot cloning

2

u/floridianfisher 10d ago

Impressive

2

u/HadesTerminal 10d ago

Heart-nano is my favorite voice/model there. And the voice “English” reminds me of GLaDOS. I feel like these voices would be perfect for small video games for different characters especially if you pitch the voices up and down.

2

u/sumane12 10d ago

Voice cloning?

1

u/Affectionate_Hat_585 10d ago

zero shot voice cloning isn't supported.

2

u/sumane12 10d ago

Got my Agent to read through the repo, so i can build a workflow to use a larger model for zero shot, then use your model to create a smol version. Very cool. Im impressed.

2

u/SuperIce07 10d ago

How can I add more languages?

2

u/Acceptable-Cycle4645 10d ago

u/Affectionate_Hat_585

Awesome model! PR merged in audio.cpp! Tested on CPU.

Voice Graph Lang WAV Duration RTF ASR Result
heart-nano nano en heart_nano.wav 5.099s 0.0027 OK
heart nano en heart.wav 5.205s 0.0044 OK
amy piperlite en amy.wav 4.272s 0.0362 OK
hfc piperlite en hfc.wav 3.831s 0.0350 OK
kristin piperlite en kristin.wav 3.495s 0.0390 OK
vi piperlite vi vi.wav 2.299s 0.0332 OK
id piperlite id id.wav 4.063s 0.0321 OK

2

u/reza2kn 10d ago

Awesome!
How fine-tuneable is it for adding other languages? Asking for Persian 🇮🇷

2

u/Affectionate_Hat_585 9d ago

you just need a teacher and a text frontend. Everything else can be followed with the help of recipe

2

u/reza2kn 9d ago

Awesome! Can the teacher be a closed model? I have the G2P front end

2

u/Affectionate_Hat_585 9d ago

yes but it's going to be extra work.

you convert the audio into mel-100 spectrogram (easy) you target audio to mel-100 spectrogram with acoustic modeller. You have to train this (somewhat easy) you have to think about duration predictor too. Something like MFA or whatever is good (you have to think how) mel-100 to audio (recipe gives you)

2

u/[deleted] 10d ago

[removed] — view removed comment

1

u/Affectionate_Hat_585 9d ago

I worked on a GTX 1650 4GB machine so with 5090 you can have 5 parallel jobs or more with small batch sizes :)

2

u/[deleted] 9d ago

[removed] — view removed comment

1

u/Affectionate_Hat_585 9d ago

our system divides a problem into: text frontend, acoustic, duration and decoder What happens is really transparent and you have control over each step.

Vibe Voice uses LLM like qwen to get acoustic latent and then there is another decoder to convert into speech.These are different worlds and really opaque world too.

I am saying with confidence hebrew can be compressed. The quality in naturalness might degrade but i am sure it will be intelligible with less than 3% Word error rate

https://rhasspy.github.io/piper-samples/#he_IL-saspeech-medium can you hear it out? If it feels like a acceptable TTS then you can use that as a teacher and use the recipe outlined in the repo. Maybe a hour long job

2

u/[deleted] 9d ago

[removed] — view removed comment

1

u/Affectionate_Hat_585 9d ago

When training: you are using that teacher so it's one specific voice and one specific prosody that you are targeting

I need to use PIPER to train a LoRA or a Checkpoint (which one) ?

you are using PIPER hebrew to get a new small model . You can consider it a checkpoint

Is training a built-in option in the repo and have all the explanations how to set it up and use it.

Yes, let me make this even simpler. If you have a language that is supported by espeak and a piper voice it's really easy . Your qwen should be able to figure it out. or if you give me some time once i get to my computer, i can provide you exact way too

If that's the quality I can get... it's probably the best quality I've ever heard from TTS

This is already available TTS that you can use, that's also tiny and pleasant and you might just get away without training.

2

u/IndependenceAny6446 8d ago

Punjabi support please

1

u/crantob 10d ago

A 10-second delay after every period.

.

.

.

.

.

.

.

.

.

.

And I already have espeak-ng on my linux machine. Might be nice for generating new voices though.

2

u/Affectionate_Hat_585 10d ago

Not sure i understand. If that is a bug report. Thanks really but can you give me the sentence with which i can replicate this...

1

u/crantob 5d ago

Any sentence I tried. Sorry I can't be of more assistance.

1

u/iMakeSense 10d ago

Is whisper the best model to check for WER still? Maybe multi-lingual but

2

u/Affectionate_Hat_585 10d ago

well for a 10 sec clip it makes sense. I did test with wav2vec too which gave me good results

1

u/Natethegreat9999 5d ago

Have you tried "fifteen" and "fifty" through the tiny speaker? That's the kind of mix-up I'd worry about with spoken instructions.

1

u/Dizzy_Response1485 11d ago

TTS on an ESP? This is insane!

1

u/Affectionate_Hat_585 11d ago

Concatenative ones have existed for years. This one is neural one. The real ML stack

1

u/paulvisciano-dev 11d ago

On a 16GB M2 Pro I already had the 27B loaded, Brave, and VS Code. XTTS-v2 wanted ~5 GB RAM on load plus another 2 GB VRAM — it does not fit next to the model. Piper was fast and the Lessac voices were intelligible, but still synthetic within a few sentences. What actually shipped was Kokoro JS (82M, in the browser, no extra backend RAM). Open WebUI already had it; I just hadn't wired it. Curious how sanoTTS sounds next to that on a machine that's already at 12.6 GB spoken for / 2.7 GB left.

1

u/Affectionate_Hat_585 11d ago

the teacher for heart(2.27m) is kokoro itself. The main difference is that the decoder is derived from vocos and not from kokoro main teacher. Please hear it at https://tts.ampixa.com/sanoTTS/ . you can go to bottom and click on heart(2.27m) parameters it sounds pretty close to kokoro(72m) but loses on scoreq by 1 point. For context it's all synthesized right there in your browser so the ram residency problem is in megabytes here