Skip to main content

poto-tts

Ghanaian English speech synthesis on sherpa-onnx. A 104,623-word Ghanaian lexicon is compiled into an espeak-ng dictionary, so names, places and titles come out right from plain text.

                stock espeak                  poto-tts
Kwabena         kwˈeɪbnə                      kwɑːbˈɪnɑː
Achimota        ɐtʃɪmˈoʊɾə                    ɑːtʃimˈoɾɑː
Okuapenhene     ˈoʊkjuːˌeɪpənhˌiːn            okwɑːpɛnhˈɛnɛ
Nyankpani       nˌaɪɐŋkpˈɑːni                 njɑːŋkpˈɑːni
Gyasi           dʒaɪʲˈɑːsi                    dʒˈɑːsi

Ordinary English is untouched: yesterday keeps its own stress. Compiling the lexicon in, rather than looking it up at runtime, means callers ship no lexicon file and words the lexicon never had are still spoken — espeak's own rules handle them.

pip install poto-tts
poto-tts "Kwabena went to Achimota" -o out.wav
from poto_tts import load

tts = load("kokoro")            # downloads the voice on first use
tts.save("The Okuapenhene met Nana Bawumia", "out.wav")

Backends

backend model commercial use accent from
kokoro (default) Kokoro v1.0, Apache-2.0 yes the dictionary
piper trained on Ghanaian broadcast speech no the weights and the dictionary

Both read the same espeak-ng-data, so either pronounces a Ghanaian name the same way; what differs is the voice and the licence. The piper corpus is broadcast recordings whose speakers did not consent to being modelled — research and non-commercial use only. For a commercial Ghanaian voice use kokoro, or train piper on recordings you hold rights to (tools/ takes any dataset).

tts = load("piper", voice="gh_00")
print(tts.licence, tts.commercial_use)

Models

Voices live on the Hub and are fetched through huggingface_hub, so downloads are counted:

backend repo
kokoro ghananlpcommunity/poto-tts-kokoro-gh
piper ghananlpcommunity/poto-tts-piper-gh-16k (training)

Each repo's config.json names its own files, speakers and licence, so a new voice needs no release of this library:

tts = load("kokoro", repo_id="your-org/your-voice")

POTO_TTS_CACHE moves model files off ~/.cache.

Cross-platform

sherpa-onnx runs on Android, iOS, WebAssembly, C++, C, Go, C#, Java, Kotlin, Rust, Dart and Swift, across x86, arm64, arm32 and RISC-V. Pronunciation lives in a data directory, not in Python, so a voice is a file set that any of those runtimes loads directly — offline, no server:

file
onnx/model.onnx the generator
tokens.txt phoneme → id
voices.bin speaker embeddings (Kokoro only)
espeak-ng-data/ the Ghanaian part. Ship this one.

A stock espeak-ng-data leaves a working voice that mispronounces every Ghanaian name, with no error. That directory is the deliverable.

Point your platform's sherpa-onnx TTS API at those files — Kotlin OfflineTts, Swift SherpaOnnxOfflineTts, the WASM build, or sherpa-onnx-offline-tts. Upstream docs.

REST API

pip install 'poto-tts[api]'
poto-tts serve --host 0.0.0.0 --port 8080
curl "localhost:8080/speak?text=Kwabena+went+to+Achimota" -o out.wav
endpoint
GET /health liveness, loaded voices
GET /backends engines, licences, commercial-use flags
GET /voices?backend=kokoro speaker names, recommended first
GET /platforms how to run the same voice off-server
POST /speak {"text", "backend", "voice", "speed"} → WAV
GET /speak?text=… the same, for a browser or curl

Requests over 2,000 characters are refused rather than truncated (POTO_TTS_MAX_CHARS). For phone apps, ship the files instead — no network, no latency, no server.

Changing how a word is said

The dictionary will still miss your grandmother's name. Rebuilding is the supported fix: it changes the data every runtime loads, so Android and iOS get it too. Needs the espeak-ng binary and the lexicon extra:

pip install 'poto-tts[lexicon]'
# my_words.tsv — word<TAB>pronunciation
Darkoa	d a r k o a
Kufuor	=kufu'or
poto-tts dict --out my-espeak-data --extra my_words.tsv
POTO_TTS_ESPEAK_DATA=./my-espeak-data poto-tts "Darkoa met Kufuor" -o out.wav

Values are Ghanaian IPA, mapped by the same tables as the packaged lexicon. A leading = passes raw espeak mnemonics through, and is checked: an invalid mnemonic makes espeak silently discard the rest of an entry, so the build rejects it rather than shipping half a word. Your entries override the packaged lexicon, so the file corrects entries as well as adding them.

For a quick check without rebuilding:

poto-tts --phonemes "Nana Addo met Kwame Nkrumah"
from poto_tts import GhanaInjector
GhanaInjector(lexicon={"Darkoa": "d a r k o a"})("Darkoa came home")
# "[[dA:rk'oA:]] came home"

That is a debugging tool, not a deployment route: Python-only, and Kokoro's frontend rewrites : in its input, which corrupts length marks.

How the dictionary is built

ghana-english-g2p's Ghanaian IPA is mapped to espeak mnemonics (poto_tts/mnemonics.py) and compiled into espeak's en_extra. Entries are written only for words that are not ordinary English, checked against a 370k-word list: espeak already handles English, including its stress. An earlier version that entered every word whose pronunciation differed took 93,526 of them and moved the stress in yesterday, January and Wednesday.

The build verifies its own output — no truncated entries, and espeak's English unchanged byte for byte. The vowel decisions are in the module's comments: /a/ uses A: rather than 0, which espeak reads as a different vowel before /r/; æ merges into /a/; FACE and GOAT map to the monophthongs espeak's English rules never emit but its tables define.

Training a voice

tools/ holds the pipeline behind the piper backend, and takes any dataset:

stage
prepare_dataset.py filter duration, character set, disfluency, transcript/audio mismatch
prepare_dataset.py embed ECAPA speaker embeddings on GPU
prepare_dataset.py cluster pseudo-speakers, with per-speaker and total caps
prepare_dataset.py align forced alignment, storing word timings
prepare_dataset.py segment cut at real pauses, punctuate from the silences
check_alignable.py drop utterances that crash monotonic_align
train.sh Piper VITS at the corpus's native sample rate
export_sherpa.py package a voice for sherpa-onnx

Thresholds there are measured, and the comments record the distributions they came from — including the ones that were wrong first.

Credits

sherpa-onnx (k2-fsa) · Kokoro-82M (hexgrad, Apache-2.0) · piper1-gpl (OHF Voice) · ghana-english-g2p (GhanaNLP) · espeak-ng

MIT, except the bundled espeak-ng-data (GPL-3.0) and the piper voice (non-commercial).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

poto_tts-0.3.0.tar.gz (46.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

poto_tts-0.3.0-py3-none-any.whl (42.2 kB view details)

Uploaded Python 3

File details

Details for the file poto_tts-0.3.0.tar.gz.

File metadata

  • Download URL: poto_tts-0.3.0.tar.gz
  • Upload date:
  • Size: 46.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.12

File hashes

Hashes for poto_tts-0.3.0.tar.gz
Algorithm Hash digest
SHA256 1f1520b04d0ab4959df6afd78badadf05c296f27f6677cacc16323d62e33ffae
MD5 c15c9bd22ac197ede7064a29f3e3be52
BLAKE2b-256 710fce8eff03148d709337dd25ea8ecd069284acb00f4031a3e0438d0e6466be

See more details on using hashes here.

File details

Details for the file poto_tts-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: poto_tts-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 42.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.12

File hashes

Hashes for poto_tts-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bdaf072cc916fc7fd0f6811b56b5e15c921e33c8cf018ca6a304ce1d1e30deed
MD5 66c080f15777d89c236b89ed7afddf83
BLAKE2b-256 a0db65dfd7ec387c127e4f12a9952400361e86f7b38be0a68bbb5cf8be151eb8

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.0

2 files

0.6.1

2 files

0.6.0

2 files

0.5.0

2 files

This release

0.3.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page