kokoro_tts_eu_pt — European Portuguese (pt-PT) voice
A small, permissively licensed (Apache-2.0) European Portuguese text-to-speech voice, fine-tuned from Kokoro-82M. It runs on CPU and is driven by an Apache-2.0 grapheme-to-phoneme front-end, so nothing GPL is required to install or run it.
Use it through the tts_eu_pt package
(source on GitHub):
pip install tts_eu_pt
from tts_eu_pt import TTS
tts = TTS() # downloads this repo on first run
wav = tts.say("Olá! São dezasseis horas.") # numpy float32 @ 24 kHz
tts.save("ola.wav", "Bem-vindo ao tts_eu_pt.")
tts-eu-pt "D. Afonso I reinou de 1139 a 1185." reis.wav
Files
| File | Size | What it is |
|---|---|---|
tuga_kokoro.pth |
327 MB | Acoustic model weights — encodes the language (pt-PT phonology and accent) |
tuga_voicepack.pt |
524 kB | Voicepack — encodes the speaker (timbre), a [510, 1, 256] float32 tensor |
Weights and voicepack are deliberately separate: the same weights can drive a different
speaker by swapping the voicepack. The voicepack is indexed by phoneme-string length
(pack[len(phonemes) - 1]), which is why its first dimension is 510.
Why it exists
The hard part of pt-PT TTS is not the acoustics — it is reading text the way a Portuguese
speaker actually does, and doing it without GPL dependencies. Most open TTS stacks reach
for espeak-ng (GPLv3) for G2P, which forces copyleft on anything built on top. This voice
uses TugaPhone (Apache-2.0) instead, on the
Lisbon lect (pt-PT-x-lisbon).
Handled out of the box by the tts_eu_pt front-end:
| Input | Spoken as |
|---|---|
25, 125, 1139 |
vinte cinco, cento e vinte cinco, mil cento e trinta e nove |
16:54, 16:00 |
dezasseis e cinquenta e quatro, dezasseis horas |
1139-1185 |
mil cento e trinta e nove a mil cento e oitenta e cinco |
D. Afonso I |
Dom Afonso Primeiro |
IA, LLM, UTC |
i-á, éle-éle-éme, u-tê-cê |
online, software |
kept in their English pronunciation, as pt-PT speakers say them |
Note the European-Portuguese quirk in the twenties: 21–24 keep the connector e ("vinte e quatro") while 25–29 drop it ("vinte cinco"), at every scale.
Model details
- Architecture: Kokoro (StyleTTS2-derived) — ALBERT-based text encoder, prosody
predictor, iSTFTNet decoder. Five modules:
bert,bert_encoder,predictor,text_encoder,decoder. - Parameters: 81.8 M
- Output: 24 kHz mono, float32
- Phoneme vocabulary: 178 tokens, 510-token input cap (longer text is chunked by sentence upstream)
- G2P: TugaPhone, lect
pt-PT-x-lisbon, plus a 774-entry English-loanword pronunciation table - Precision: float32; runs on CPU or CUDA
Performance
Measured on CPU (no GPU), synthesising with tts_eu_pt, median real-time factor ≈ 0.14 —
roughly 7× faster than real time, about 1 s of compute per 7 s of audio. Model load
(download excluded) is ~2.3 s.
RTF varies with utterance length, because per-call overhead dominates short inputs:
| Audio produced | Compute | RTF |
|---|---|---|
| 3.5 s | 0.93 s | 0.27 |
| 5.9 s | 0.89 s | 0.15 |
| 7.1 s | 0.95 s | 0.13 |
| 44.2 s | 5.88 s | 0.13 |
So expect ~0.13–0.15 for sentences and paragraphs, and closer to 0.27 for very short phrases. Figures are from one commodity CPU and are indicative, not a benchmark.
Intended use
General-purpose European Portuguese speech synthesis: voice assistants, screen readers, audio for accessibility, prototyping, and offline/on-device use where a GPL-free stack matters.
Limitations
- European Portuguese only. Brazilian Portuguese is not supported and will sound wrong.
- Single speaker. One voicepack ships here.
- Honorific
D.is expanded to the masculine Dom;D. Maria→ Dom Maria is wrong. Regnal numerals likewise map to masculine ordinals (Primeiro, Segundo, …), so queens are mis-gendered. - Regnal numeral mapping covers I–XX only.
- An unrecognised lect string silently falls back to generic pt-PT rather than raising.
- Four TugaPhone symbols fall outside Kokoro's vocabulary and are mapped or dropped: uvular trill ʀ→ʁ, dark ɫ→l, ASCII g→ɡ, and the apico-alveolar diacritic (dropped — a genuine pt-PT feature the vocabulary cannot represent).
- No formal listener evaluation has been run yet. There is no MOS score for this voice; quality claims here are architectural and objective-metric based, not perceptual. Judge it by listening before relying on it in production.
Out-of-scope / misuse
Do not use it to impersonate a real person or to generate speech presented as a genuine recording of someone. Synthetic speech should be disclosed as synthetic.
Training
Fine-tuned from Kokoro-82M on European Portuguese, with the voicepack extracted separately from a single-speaker corpus, so that language and timbre stay disjoint. Training used the same TugaPhone G2P as inference — a mismatch between training-time and inference-time phonemisation is the classic way to wreck a fine-tune of this kind.
Licensing
Apache-2.0, and everything required to run it is permissively licensed.
| Component | License |
|---|---|
| These weights + voicepack | Apache-2.0 (fine-tuned from Apache-2.0 Kokoro-82M) |
Kokoro acoustic model code (vendored in tts_eu_pt) |
Apache-2.0 |
| TugaPhone (pt-PT G2P) | Apache-2.0 |
| PyTorch | BSD-3-Clause |
The upstream Kokoro KPipeline is not used, because it pulls in GPLv3 espeak-ng via
misaki. Only the acoustic KModel is. The English-loanword pronunciation table was
generated offline with espeak-ng at data-prep time; only the resulting phoneme strings
are distributed, as data — espeak-ng is not a runtime dependency and is not redistributed.
The Kokoro architecture derives from StyleTTS2 (MIT).
Citation
@misc{kokoro_tts_eu_pt,
title = {kokoro_tts_eu_pt: a permissively-licensed European Portuguese TTS voice},
author = {Cruz, Antonio},
year = {2026},
url = {https://huggingface.co/logus2k/kokoro_tts_eu_pt}
}
Acknowledgements
hexgrad for Kokoro-82M, and TigreGotico for TugaPhone.