Kusaal TTS (VITS)
Author: Prince Nasamu Alhassan
Overview
Fine-tuned from facebook/mms-tts-kus.
20,000 steps on kusaal_scripture.
Register warning. The only Kusaal voice data available is scripture, so this voice reads rather than speaks. That is the data, not the training. A native speaker confirmed it handles non-scripture text correctly, so the phoneme coverage generalises even though the register does not.
A truncation report, and what came of it. The same speaker reported that the 6,000-step version did not always finish a sentence. VITS trains its duration predictor more slowly than its acoustic model, which produces exactly that symptom, so the run was extended to 20,000 steps. TTS/measure_truncation.py in the project repository measures it rather than asking anyone to trust an ear: it synthesises sentences a human recorded and divides our duration by theirs.
What that measurement found. At 20,000 steps the voice reads scripture at 0.89 of human duration, and agent commands at 0.54. The cause is not the step count: MMS-VITS tokenisers are character-level, and a character outside the 35-entry Kusaal vocabulary is dropped silently. On agent commands, of the characters given to the voice:
| text sent to the voice | characters deleted |
|---|---|
| raw | 21.2% |
after agent_core.verbalize_numbers, which the agent runtime calls |
1.3% |
after TTS/speak_mixed.py also routes unsayable words |
0.0% |
The remaining 1.3% was entirely c and q, so cedis was spoken as edis -- the word naming the money in a payment confirmation.
Use it
import torch, soundfile as sf
from transformers import AutoTokenizer, VitsModel
repo = "PrinceAlhassanNasamu/tekyerema-tts-kus"
tok = AutoTokenizer.from_pretrained(repo)
model = VitsModel.from_pretrained(repo).eval()
with torch.no_grad():
wav = model(**tok("your text here", return_tensors="pt")).waveform[0]
sf.write("out.wav", wav.numpy(), model.config.sampling_rate)
Read this before sending it real text. These VITS tokenisers are CHARACTER-level, and a character outside the vocabulary is dropped silently — no error, no gap in the audio. Measured on Kusaal agent commands, raw text loses 21.2% of its characters, and digits go entirely: "Send 20 cedis to 0551112233" is spoken as "Send cedis to".
Spell numbers into words before synthesis, and route any word whose letters this voice lacks to a voice that has them.
AGENT/agent_core.pydoes both —verbalize_numbersandsayable_segments— which takes the loss to 0.0%.
Training data
Trained on the Ghana Speech dataset and related Ghanaian corpora, licensed CC BY-NC 4.0.
Intended use & license
Non-commercial use only (CC BY-NC 4.0). This is inherited from the training data and required by the terms under which the compute was granted: models trained in that window are non-commercial by condition of access, not by inference.
Limitations, stated plainly
- Dagbani had no recogniser of its own for this whole project, and the
reason given for that was wrong. Every card here said "one fine-tuning
session on 74 validation rows would not change that". Those 74 rows are
the eng-dag machine-translation validation split. The Dagbani
speech data in this same account is
waxal_dag: 13,228 training rows, 1,750 validation rows, ~71 hours, 1,041 speakers with the largest at 1% — more data and better speaker diversity than Ewe, which produced a working 42.19 WER recogniser. A number was carried across from a translation table into a speech claim, and then repeated on every model card on the account. It is training now, on 2026-08-31. Until it is scored, the honest statement is that Dagbani's best available recogniser scores 86.6 WER and nobody had tried fine-tuning on the data already in hand. - Evaluation is on read and machine-translated text. No recordings of people speaking agent commands in these languages exist. Numbers measured this way are optimistic about phrasing and pessimistic about code-switching, and should not be read as field performance.
- Research work from a hackathon entry, not a supported product.
The rest of the family
Recognisers
whisper-large-v3-turbo-tekyerema-eng-foundation— Ghanaian English ASR — course 1 (foundation)kusaal-whisper-small-lora— Kusaal ASR (Whisper-small LoRA, superseded)kasa42-asr— KASA-42 (Kusaal, third-party export)tekyerema-asr-ctc— Twi ASR (w2v-BERT CTC)tekyerema-asr-mms-ewe— Ewe ASR (MMS adapter)tekyerema-asr-mms-dag— Dagbani ASR (MMS adapter)tekyerema-asr-mms-hau— Hausa ASR (MMS adapter)tekyerema-asr-mms-kus— Kusaal ASR (MMS adapter)whisper-large-v3-turbo-tekyerema-eng— Ghanaian English ASR (Whisper large-v3-turbo)
Voices
tekyerema-tts-twi— Twi TTS (VITS)tekyerema-tts-kus— Kusaal TTS (VITS)tekyerema-tts-ewe— Ewe TTS (VITS)tekyerema-tts-hau— Hausa TTS (VITS)tekyerema-tts-eng— Ghanaian English TTS (VITS)
Agent models
tekyerema-1-reply— Tɛkyerɛma-1 reply adapter (arm ①)tekyerema-1-native-reply— Tɛkyerɛma-1 reply adapter (arm ②)tekyerema-1-tool— Tɛkyerɛma-1 tool adapter (arm 1)tekyerema-audio-native— Tɛkyerɛma-1 audio-native (arm 3)tekyerema-audio-native-4k— Tɛkyerɛma-1 audio-native, 4,000 clips (arm 3 v2)tekyerema-1-native-tool— Tɛkyerɛma-1 tool adapter (arm 2)
Translation
tekyerema-nllb600m-v1— Tɛkyerɛma MT v1 (NLLB-600M)kusaal-nllb-600M— Kusaal MT specialist (NLLB-600M)
Routing
tekyerema-intent-afroxlmr— Intent classifier (AfroXLMR)
Acknowledgements
Compute resources provided by AI Skills and Compute Africa (AISCA).
Trained on the Ghana NLP H200 GPU. Please keep derivatives non-commercial
and share improvements back with the Ghana NLP community
(ghananlpcommunity).
- Downloads last month
- 310
Model tree for PrinceAlhassanNasamu/tekyerema-tts-kus
Base model
facebook/mms-tts-kus