I built a Windows app that runs Silero, XTTS-v2 and F5-TTS locally: sizes, speeds and the gotchas
I often need to voice a script, and online text-to-speech services with a free character limit and a subscription after it got old. A modern GPU runs neural speech synthesis happily, so I built a small desktop wrapper ar
I often need to voice a script, and online text-to-speech services with a free character limit and a subscription after it got old. A modern GPU runs neural speech synthesis happily, so I built a small desktop wrapper around it: Glasvo. A tkinter window with three engines: Silero, Microsoft Edge voices and voice cloning (XTTS-v2 and F5-TTS). MIT licensed, Windows 10/11.
It was made first of all for Russian, but English works too (118 English Silero voices, English XTTS and F5 cloning). Here is what it costs in disk, memory and time, and the things that bit me.
What it needs
| Download | about 8 MB zip (the installer fetches the rest) |
| After install | about 5.5 GB: Python 3.12, PyTorch 2.5.1 (CUDA 12.1) and 168 packages, all inside the app folder |
| Silero models | 40β140 MB each (v5_ru 139 MB), downloaded on first use |
| XTTS-v2 | 2.0 GB |
| F5-TTS (Russian checkpoint + vocos) | 1.4 GB |
| Whisper small (sample transcription for F5) | 0.9 GB |
| Everything | about 10 GB |
| GPU | optional for Silero and Edge. XTTS/F5 need NVIDIA: measured peak 2 GB of VRAM on an RTX 3070 (8 GB), 6 GB+ recommended |
| RAM | about 1.2 GB with Silero, about 3 GB with XTTS/F5 |
Measured on the same 285-character Russian paragraph (about 18 seconds of speech), RTX 3070, after warm-up:
| Engine | Time | Model load | Peak VRAM |
|---|---|---|---|
| Silero v5_ru, GPU | 0.08 s | fast | 242 MB |
| Silero v5_ru, CPU | 0.53 s | ||
| XTTS-v2 | 5 s for 18.7 s of audio | 13 s | 2019 MB |
| F5-TTS | 4.4 s for 17.3 s of audio | 4 s | 1999 MB |
These are single runs on one machine, not a benchmark, but the order of magnitude is clear: Silero is hundreds of times faster than real time, cloning a few times.
Silero details
Silero models are torch.package archives. PyTorch refuses to open a path with Cyrillic characters, and users' folders can be anything, so I pass a file object:
with open(path, "rb") as f:
model = PackageImporter(f).load_pickle("tts_models", "model")
model.to(torch.device("cuda")) # or "cpu"
wav = model.apply_tts(text=chunk, speaker="xenia", sample_rate=48000,
put_accent=True, put_yo=True)
Speed and pitch go through SSML (<prosody rate= pitch=>), and a chunk should stay under about 700 characters, so long text is split at sentence boundaries and joined with a pause.
The nasty surprise: Silero's Russian models silently skip digits and drop Latin letters. You get gaps, not errors. Two functions run before the model: expand_numbers (built on num2words) turns 2026 into words, and latin_to_cyrillic handles Latin text in three levels: a dictionary for common words (YouTube becomes Β«ΡΡΡΠ±Β»), letter-by-letter for ALL CAPS and vowel-less tokens (USB becomes Β«Ρ-ΡΡ-Π±ΠΈΒ»), transliteration for the rest. I checked it by synthesizing test phrases and recognizing them back with Whisper.
Cloning
The sample goes through ffmpeg (taken from imageio-ffmpeg, so no system ffmpeg is needed) to mono 24 kHz wav, written to a temp file and moved with os.replace, so a bad file can't corrupt the previous sample. XTTS-v2 has a limit of about 182 characters per Russian chunk, so chunks are 170. F5 needs the reference text, so Whisper small transcribes the sample locally and then unloads to free VRAM.
My check: use a Silero voice as the "sample", have XTTS and F5 read a text with it, transcribe the result with Whisper and compare the words. 100% match for both.
Dependency hell
Cloning (coqui-tts, f5-tts, transformers) pulls in so much that resolvers choke. What is pinned: torch==2.5.1+cu121 (transformers 5 and diffusers 0.43 need torch 2.6+), transformers<5, huggingface_hub<1.0, and omegaconf==2.3.1 (hydra needs it for F5). pip check complains about f5-tts pins, which is fine. requirements.txt is an exact pip freeze of the working environment.
Installing for people without Python
install.bat runs install.ps1, which downloads uv, installs Python 3.12 into the app folder, creates a venv and runs uv pip install --no-deps -r requirements.txt. Without an NVIDIA GPU it swaps torch +cu121 for +cpu. The uv cache lives in a short temp path, because antlr4 failed to build in a deep folder. Models are not in the zip: they are downloaded on first use with huggingface_hub.snapshot_download.
The app updates itself: on start it reads releases/latest from GitHub, downloads Glasvo.zip and copies files over the old ones except settings.json.
Small things
- Under
pythonw,sys.stdoutisNoneand tqdm/print crash. I putdevnullthere. - Background threads must not touch tkinter. Everything goes through a queue that the main thread drains on a timer.
- The mouse wheel over a
ttk.Comboboxchanges its value; I intercept it. - Ctrl+C/V/X/A with a Russian keyboard layout: match by keycode.
Licences
Code is MIT. Most models are non-commercial: Silero and the Russian F5-TTS are CC BY-NC 4.0, XTTS-v2 uses the Coqui Public Model License. Check them before using audio in monetized videos, and clone only your own voice or one whose owner agreed.
Download: https://github.com/OlegChe77/glasvo/releases/latest/download/Glasvo.zip
Source: https://github.com/OlegChe77/glasvo
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.
