Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 4 min read

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 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 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.

Glasvo: the Silero page

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.

Voice cloning page

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.stdout is None and tqdm/print crash. I put devnull there.
  • 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.Combobox changes 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

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.