A Swahili text-to-speech voice, finetuned from F5-TTS (F5TTSv1Base, Emilia-pretrained). Flow-matching DiT (1024-dim, 22 layers) + Vocos vocoder, 24 kHz mono, character tokenizer. It is reference-conditioned...
Model source
Source description
A Swahili text-to-speech voice, finetuned from (, Emilia-pretrained). Flow-matching DiT (1024-dim, 22 layers) + vocoder, mono, character tokenizer. It is : it speaks the target text in the voice of a short reference clip (3–10 s). An embedded reference () is included so it works text-only out of the box.
Sources
1 sourceVerified Sep 22
Model artifacts
1 artifactSource excerpts
2 excerptsF5TTS_v1_Basereference.wavsw, n=25). See the benchmark below.stem-content-ai-project/swahili-speech.| File | Description |
|---|---|
model.safetensors | Pruned EMA weights (finetune of F5TTS_v1_Base) |
vocab.txt | Character vocab (reused from the Emilia base) |
reference.wav / reference.txt | Embedded reference clip + transcript (Safari voice, ~6.9 s) |
Apples-to-apples: every row was evaluated identically — the same 25 held-out Swahili
sentences, the same Safari reference clip, transcribed with the same ASR (Whisper-large-v3 sw).
Only the finetuning data changes (all share the F5TTS_v1_Base Emilia base). Lower is better.
| # | Finetuning data | Eff. hours | CER (raw) | WER (raw) |
|---|---|---|---|---|
| 1 | none — F5TTS_v1_Base zero-shot (Emilia: EN/ZH only) | 0 | 0.175 (0.175) | 0.638 (0.639) |
| 2 | + ~1.5 h studio (Safari/Toby) | ~1.5 | 0.173 (0.174) | 0.622 (0.624) |
| 3 | + FLEURS-R sw | 10.6 | 0.080 (0.087) | 0.346 (0.369) |
| 4 | + FLEURS + studio (overweighted 3×) | 15.2 | 0.043 (0.051) | 0.268 (0.285) |
| 5 | + Common Voice + FLEURS + studio ⭐ (this model) | 29.3 | 0.029 (0.039) |
Headline numbers are text-normalized (punctuation stripped, digits expanded on both the reference and the ASR hypothesis — standard TTS-eval practice, cf. Seed-TTS eval / Whisper normalizers). Raw lowercase-only scores in parentheses: they count ASR-added punctuation and digit re-formatting as errors, inflating CER ~25% relative at this level.
ng', ny, dh, prenasalized stops).sw mis-spells/segments, so WER over-states errors. CER
and listening are the reliable signals.Methodology note: the common set is the published model's held-out split; older models pre-date it, so any overlap with their training would flatter them — the swbase margin is therefore conservative. Numbers were produced with this repo's eval (synthesize → Whisper-large-v3
sw→ CER/WER vs target).
from huggingface_hub import hf_hub_download
from f5_tts.api import F5TTS # pip install f5-tts
repo = "stem-content-ai-project/f5-tts-sw"
ckpt = hf_hub_download(repo, "model.safetensors")
vocab = hf_hub_download(repo, "vocab.txt")
ref = hf_hub_download(repo, "reference.wav")
ref_text = "Shughuli za mwovodhaji zilisaidia katika uokoaji wa samahani zilizozama."
tts = F5TTS(model="F5TTS_v1_Base", ckpt_file=ckpt, vocab_file=vocab)
# 1) PRE-PROCESS the text (see below), then 2) synthesize.
gen_text = preprocess("Piga *149*00# kulipa shilingi 2500.") # -> Swahili words
wav, sr, _ = tts.infer(ref_file=ref, ref_text=ref_text, gen_text=gen_text)
To use a different voice, pass your own ref_file / ref_text (3–10 s of clean speech).
The model was trained on text where numbers are spelled out as Swahili words and only
, . ? ! ' - punctuation appears — it never saw digit/symbol glyphs. Real input has digits, %,
USSD codes, etc., so normalize first. This is a sample, swappable heuristic — call it in sequence
before infer, or drop in your own frontend:
import re
ONES = ["sifuri","moja","mbili","tatu","nne","tano","sita","saba","nane","tisa"]
TENS = {10:"kumi",20:"ishirini",30:"thelathini",40:"arobaini",50:"hamsini",
60:"sitini",70:"sabini",80:"themanini",90:"tisini"}
SYM = {"*":" nyota ","#":" alama ya reli ","/":" kwa ","+":" jumlisha ",
"=":" sawa na ","&":" na ","@":" at ","_":" "}
_KEEP = re.compile(r"[^A-Za-zÀ-s .,?!'\-]")
def _two(n): return ONES[n] if n<10 else TENS.get(n) or f"{TENS[n//10*10]} na {ONES[n%10]}"
def _three(n):
h,r=divmod(n,100); p=[]
if h: p+=["mia",ONES[h]]
if r: p.append(("na "+_two(r)) if h else _two(r))
return " ".join(p)
def cardinal(n):
if n==0: return "sifuri"
p=[]
for v,name in [(10**9,"bilioni"),(10**6,"milioni"),(1000,"elfu")]:
if n>=v: q,n=divmod(n,v); p.append(f"{name} {_three(q)}")
if n: p.append(("na "+_three(n)) if p and n<100 else _three(n))
return " ".join(p)
def digits(s): return " ".join(ONES[int(c)] for c in s if c.isdigit())
def _num(t): return digits(t) if (len(t)>=5 or t.startswith("0")) else cardinal(int(t))
def preprocess(text: str) -> str:
text = text.strip()
text = re.sub(r"\*[\d*#]*#", lambda m: " "+re.sub(r"\d+",lambda d:digits(d.group()),m.group())+" ", text) # USSD *149*00#
text = re.sub(r"(\d+)\s*%", lambda m: " asilimia "+cardinal(int(m.group(1)))+" ", text) # 50% -> asilimia hamsini
for s,w in SYM.items(): text = text.replace(s,w) # symbols -> words
text = re.sub(r"\d+", lambda m: " "+_num(m.group())+" ", text) # remaining numbers
text = _KEEP.sub(" ", text) # drop unknown glyphs
text = re.sub(r"\s+([,.?!])", r"\1", re.sub(r"\s+"," ",text)).strip()
return text
Examples (call order: digits/codes → percent → symbols → number words → strip → collapse):
| Input | preprocess(...) |
|---|---|
Piga *606# kuangalia salio. | Piga nyota sita sifuri sita alama ya reli kuangalia salio. |
Lipa shilingi 2500 kwa siku. | Lipa shilingi elfu mbili na mia tano kwa siku. |
Punguzo la 50% leo. | Punguzo la asilimia hamsini leo. |
Akaunti 0712345678. | Akaunti sifuri saba moja mbili tatu nne tano sita saba nane. |
Heuristics it encodes (replace if your domain differs): ≥5-digit or leading-zero runs (phone/PIN/
account) are read digit-by-digit; shorter runs use cardinal words; % → asilimia N; USSD
*...# → every digit spoken; unsupported glyphs are dropped.
F5TTS_v1_Base (finetune), char tokenizer, Vocos @ 24 kHz, bf16 + TF32, batch 3200 frames.sw (cleaned) + Common Voice sw v17 (cleaned + quality-filtered)
sw) → CER/WER vs the target text, with text normalization (punctuation strip + digit expansion)
applied to both sides before scoring.runs/ — see the Metrics tab on this page.| Source | License | Role |
|---|---|---|
FLEURS-R sw | CC-BY-4.0 | pronunciation breadth (Kenyan-leaning) |
Common Voice sw v17 | CC0 | scale + Tanzanian-accent breadth |
Safari (stem-content-ai-project/swahili-speech) | — | studio target; embedded voice |
| Toby | Vodacom (internal) | IVR-domain influence only |
The Toby set is Vodacom-internal and used purely as a training-distribution influence; the model's output voice is the Safari speaker, not the Toby speaker.
2500, %, *...# are unseen glyphs and come out
wrong or dropped.sw mis-spells); use CER + listening.ref_text accurate.vocab.txt (the char set the
weights expect).torchaudio.load dispatches to
torchcodec and fails to find FFmpeg — read audio via soundfile instead (monkeypatch
torchaudio.load), and for ASR use WhisperProcessor + model.generate rather than the
transformers pipeline (which hard-imports torchcodec).ng', prenasalized stops); a
domain pronunciation lexicon helps for brand/technical terms.Non-commercial (CC-BY-NC-4.0) — inherits the NC terms of the F5TTS_v1_Base (Emilia) base model.
Single embedded voice (Safari); for other voices supply your own reference.
Built on F5-TTS (SWivid et al.), FLEURS-R (Google), Mozilla Common
Voice, Vocos, and the stem-content-ai-project/swahili-speech corpus.
--- license: cc-by-nc-4.0 language: - sw library_name: f5-tts pipeline_tag: text-to-speech base_model: SWivid/F5-TTS tags: - text-to-speech - tts - f5-tts - swahili - speech-synthesis datasets: - google/fleurs - mozilla-foundation/common_voice_17_0 - stem-content-ai-project/swahili-speech metrics: - cer - wer model-index: - name: f5-tts-sw results: - task: type: text-to-speech dataset: name: held-out Swahili test (FLEURS-R + Common Voice + Safari + Toby) type: mixed metrics: - type: cer value: 0.029 name: Character Error Rate (text-normalized, Whisper-large-v3 sw, n=25) - type: wer value: 0.202 name: Word Error Rate (text-normalized, Whisper-large-v3 sw, n=25) --- # F5-TTS Swahili (f5-tts-sw) A **Swahili** text-to-speech voice, finetuned from [F5-TTS](https://github.com/SWivid/F5-TTS) (`F5TTS_v1_Base`, Emilia-pretrained). Flow-matching DiT (1024-dim, 22 layers) + [Vocos](https://huggingface.co/charactr/vocos-mel-24khz) vocoder, **24 kHz** mono, character tokenizer. It is **reference-conditioned (zero-shot)**: it speaks the target text in the voice of a short reference clip (3–10 s). An embedded reference (`reference.wav`) is included so it works text-only out of the box. - **Best in our bench: CER 0.029 / WER 0.202** (text-normalized; raw 0.039 / 0.228 — Whisper-large-v3 `sw`, n=25). See the benchmark below. - **Embedded voice:** the *Safari* speaker — a clean studio voice from [`stem-content-ai-project/swahili-speech`](https://huggingface.co/datasets/stem-content-ai-project/swahili-speech). ## Files | File | Description | |---|---| | `model.safetensors` | Pruned EMA weights (finetune of `F5TTS_v1_Base`) | | `vocab.txt` | Character vocab (reused from the Emilia base) | | `reference.wav` / `reference.txt` | Embedded reference clip + transcript (Safari voice, ~6.9 s) | ## Benchmark — what each ingredient buys you **Apples-to-apples:** every row was evaluated **identically** — the *same* 25 held-out Swahili sentences, the *same* Safari reference clip, transcribed with the *same* ASR (Whisper-large-v3 `sw`). Only the **finetuning data** changes (all share the `F5TTS_v1_Base` Emilia base). Lower is better. | # | Finetuning data | Eff. hours | CER (raw) | WER (raw) | |---|---|---|---|---| | 1 | **none** — `F5TTS_v1_Base` zero-shot (Emilia: EN/ZH only) | 0 | 0.175 (0.175) | 0.638 (0.639) | | 2 | + ~1.5 h **studio** (Safari/Toby) | ~1.5 | 0....
Source context: 42 downloads · 0 likes · Pipeline text-to-speech · Library f5-tts · Repo stem-content-ai-project/f5-tts-sw