HolosTTS
HolosTTS is an open-source Ukrainian text-to-speech model, with the best balance of quality and speed (the first audio chunk in 5 ms on an RTX 3090). It has preset voices and clones a voice from an audio sample. It produces mono audio at 24 kHz and supports streaming. It runs on PyTorch, or on ONNX Runtime without PyTorch: CPU (including INT8), CUDA and TensorRT.
Demo · Models on Hugging Face · Code on GitHub
| Package | Use |
|---|---|
holos-tts |
PyTorch inference and voice cloning. |
holos-tts-onnx |
ONNX Runtime inference without PyTorch: CPU, CUDA, TensorRT. |
Phonemes
Both packages take phonemes, not text. Stress marks and phonetic transcription for Ukrainian come from separate packages on GitHub (Git is required):
python -m pip install git+https://github.com/patriotyk/ukrainian-word-stress.git \
git+https://github.com/patriotyk/ipa-uk.git
from ipa_uk import ipa
from ukrainian_word_stress import Stressifier
stressify = Stressifier()
phonemes = ipa(stressify("Привіт! Це український синтез мовлення."))
Synthesize long texts sentence by sentence.
PyTorch
python -m pip install holos-tts
NVIDIA GPUs need a CUDA build of PyTorch. The model downloads holos.pt and voices.pt from Hugging Face and caches them locally.
import torch
import soundfile as sf
from holos.models import HolosTTS
device = "cuda" if torch.cuda.is_available() else "cpu"
model = HolosTTS("patriotyk/HolosTTS", device=device)
print(model.list_voices())
voice = model.list_voices()[0]
audio = model.generate(phonemes, voice=voice, speed=1.0)
sf.write("speech.wav", audio.squeeze().cpu().numpy(), 24000)
speed above one speaks faster, below one slower. For local files, use HolosTTS("holos.pt", device=device, voices_path="voices.pt").
Streaming
stream() yields audio in chunks of chunk_frames frames (40 frames = 1 s by default) as soon as each one is ready. The chunks concatenate to the same audio as generate():
for chunk in model.stream(phonemes, voice=voice):
play(chunk.squeeze().cpu().numpy()) # tensor [1, samples]
Every utterance starts with the silence of a boundary token (about 50 ms). stream() drops it except 10 ms and fades in over 5 ms to avoid a click; trim_silence=False keeps it. A smaller chunk_frames gets the first audio out sooner but takes longer overall, since every chunk is decoded with context on both sides.
Voice cloning
reference.wav is a recording of the target voice without music or other speakers:
from holos.models import VoiceEncoder
encoder = VoiceEncoder("patriotyk/HolosTTS", device=device)
with torch.inference_mode():
custom_voice = encoder("reference.wav")
audio = model.generate(phonemes, voice=custom_voice)
sf.write("custom_voice.wav", audio.squeeze().cpu().numpy(), 24000)
voice_encoder.pt is downloaded automatically; preset voices do not need it. The voice is a vector of 256 numbers that you can save and pass to the ONNX runtime as custom_voice.squeeze().cpu().numpy().
ONNX Runtime
holos-tts-onnx runs the model on ONNX Runtime without PyTorch: on CPU (FP32 or INT8), CUDA and TensorRT, with the same streaming as above.
python -m pip install holos-tts-onnx # CPU and CUDA
python -m pip install "holos-tts-onnx[tensorrt]" # plus TensorRT
See the package README for usage, the models and GPU setup.
Benchmarks
- RTF (real-time factor) is for synthesizing a whole sentence (
generate()in HolosTTS): the time it takes divided by the duration of the audio. 0.01 means one second of speech in 10 ms; lower is faster. - First audio is the delay a listener notices: for HolosTTS, the first chunk of streaming with
stream(). The models marked * do not stream within a sentence, so their first audio is the whole sentence.
Three sentences of 5–12 s of speech, the median of 10 runs (5 on CPU) after a warm-up; the first audio is averaged over the sentences. Every sample says "Будь ласка, зателефонуйте мені завтра після обіду, коли матимете вільну хвилинку."
NVIDIA RTX 3090
| Model | Runtime | RTF | First audio | Sample |
|---|---|---|---|---|
| HolosTTS | ONNX, TensorRT FP16 | 0.0013 | 5 ms | Listen |
| HolosTTS | ONNX, TensorRT FP32 | 0.0031 | 12 ms | Listen |
| HolosTTS | ONNX, CUDA | 0.0039 | 14 ms | Listen |
| Supertonic 3 | ONNX, CUDA | 0.0052 | 45 ms* | Listen |
| StyleTTS2 single-speaker | PyTorch | 0.0065 | 55 ms* | Listen |
| Kokoro-82M (English) | PyTorch | 0.0067 | 45 ms* | Listen |
| HolosTTS | PyTorch | 0.011 | 65 ms | Listen |
| StyleTTS2 multi-speaker | PyTorch | 0.013 | 105 ms* | Listen |
| StyleTTS2 single-speaker | ONNX, CUDA | 0.013 | 112 ms* | Listen |
Intel Core i7-13700K
| Model | Runtime | RTF | First audio | Sample |
|---|---|---|---|---|
| HolosTTS | ONNX INT8 | 0.044 | 110 ms | Listen |
| HolosTTS | ONNX FP32 | 0.066 | 147 ms | Listen |
| HolosTTS | PyTorch | 0.074 | 196 ms | Listen |
| StyleTTS2 single-speaker | ONNX | 0.132 | 1104 ms* | Listen |
| Kokoro-82M (English) | PyTorch | 0.137 | 923 ms* | Listen |
| StyleTTS2 single-speaker | PyTorch | 0.138 | 1154 ms* | Listen |
| Supertonic 3 | ONNX | 0.186 | 1582 ms* | Listen |
| StyleTTS2 multi-speaker | PyTorch | 0.335 | 2756 ms* | Listen |
Apple M2
| Model | Runtime | RTF | First audio | Sample |
|---|---|---|---|---|
| HolosTTS | ONNX INT8 | 0.086 | 204 ms | Listen |
| HolosTTS | PyTorch (CPU) | 0.107 | 351 ms | Listen |
| HolosTTS | ONNX FP32 | 0.129 | 289 ms | Listen |
The other models run the way their packages do by default, and like HolosTTS they get the text already converted to phonemes, except Supertonic, which reads the text itself:
- Supertonic 3: the
supertonicpackage with 8 steps and the F1 voice (44.1 kHz); on the GPU with the CUDA provider enabled. On the i7-13700K it is about 1.7x faster when limited to 4 threads; the table uses the default. - StyleTTS2 single-speaker and multi-speaker: my earlier Ukrainian StyleTTS2 models, with the same phonemes. The single-speaker model has an iSTFTNet decoder, the multi-speaker one HiFi-GAN. The single-speaker ONNX model runs on ONNX Runtime directly, after normalizing one negative
Transposepermutation that ONNX Runtime 1.28 rejects. - Kokoro-82M does not speak Ukrainian; it is measured on English translations of the same sentences, with the af_heart voice.
Run the HolosTTS measurement on your machine from a checkout of this repository:
python benchmark.py onnx # ONNX FP32 on CPU
python benchmark.py onnx --model patriotyk/HolosTTS/onnx-int8 # ONNX INT8 on CPU
python benchmark.py onnx --provider tensorrt-fp16 # or cuda, tensorrt
python benchmark.py torch --device cuda # PyTorch
Files on Hugging Face
| File | Contents |
|---|---|
holos.pt |
PyTorch model weights and the phoneme vocabulary. |
voices.pt |
Preset voices: names and 256-dimensional vectors. |
voice_encoder.pt |
The model that computes a voice vector from an audio sample. |
samples/ |
The audio samples from Benchmarks. |
onnx/ |
FP32 ONNX model for holos-tts-onnx: CPU, CUDA and TensorRT. |
onnx-int8/ |
INT8 ONNX model for CPU. |
Each ONNX folder holds holos_onnx.json (vocabulary and parameters), voices.npz (preset voices) and the model stages: encoder.onnx, prosody.onnx, decoder.onnx, plus source.onnx and decoder_window.onnx for streaming.
License
The code and models are released under the MIT license.
Metadata
Release files for holos-tts 0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| holos_tts-0.4.tar.gz | 27.5 kB | With provenance | Details for holos_tts-0.4.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| holos_tts-0.4-py3-none-any.whl | Python 3 | none | any | Details for holos_tts-0.4-py3-none-any.whl |
Total release size: 53.0 kB
Release files / holos_tts-0.4.tar.gz
| Download URL | holos_tts-0.4.tar.gz |
|---|---|
| Size | 27.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ac254ad34f08778dedaf35ef3ebe8ff3f16e421cdbf1192fe6b9f8c964926a2
|
|
BLAKE2b-256 checksum How to use checksums |
ac616d89a6475e9d6988d0b057e4dd3975c70a13dce93f997fa7e1d5eee3c746
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logRelease files / holos_tts-0.4-py3-none-any.whl
| Download URL | holos_tts-0.4-py3-none-any.whl |
|---|---|
| Size | 25.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d819be27c38f40c9e18cd7abcc957eb5f13f3f47d30db88bcb8ba8c41edff309
|
|
BLAKE2b-256 checksum How to use checksums |
586ffe151ab706853b370e9c84b3c8f8a89a9fe9fab8ef29284a7cb3ba709735
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logSecurity for holos-tts 0.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for holos_tts-0.4.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.