Skip to main content

Cairo-TTS

Cairo-TTS · كايرو

Fast Egyptian Arabic text-to-speech with English code-switching, live streaming and zero-shot voice cloning.
It runs on CPU or GPU, starts speaking in under 100 ms on a GPU, and includes 20 preset voices and a web studio.

Model Space Open in Colab PyPI Python MIT

Install · Python · Web studio · Colab · Space · Pronunciation · Preprocessing · Parameters


from cairo_tts import CairoTTS

tts = CairoTTS.from_pretrained()          # downloads mohammedaly22/Cairo-TTS, runs on CPU
tts.save("ال meeting بكره الصبح بدري, ف يا ريت متتأخرش.", "out.wav", voice="malak")

✨ Features

🗣️ Egyptian Arabic Trained on ~747 h of Egyptian podcasts collected with the EgySpeech pipeline. It reads everyday عامية naturally.
🔀 Code-switching English words inside Arabic sentences: «ال deadline بتاع ال project».
🎙️ Zero-shot cloning Clone any voice from a ~10 s recording, or use one of the 20 preset voices (10 male, 10 female).
⚡ Streaming Audio comes out in 80 ms frames while it is generated: ~80 ms to first audio on a GPU.
💻 CPU or GPU ~100M parameters, faster than real time on a laptop CPU, with optional int8.
🔢 Egyptian text frontend Numbers, dates, times, money, %, phone numbers, emails, URLs, hashtags and acronyms are read the Egyptian way.
✍️ Pronunciation control Diacritics override the model's reading; ةْ gives a pronounced ta marbuta, and ~ the Egyptian reading of a letter.
🎛️ Web studio An RTL Arabic UI with generate and stream modes, voices, cloning, parameters, live waveform and metrics, and light/dark themes.

📦 Install

pip install cairo-tts            # Python API + CLI
pip install "cairo-tts[ui]"      # + web studio (FastAPI)

From source:

git clone https://github.com/MohammedAly22/Cairo-TTS && cd Cairo-TTS
pip install -e ".[ui]"
  • GPU: install the CUDA build of PyTorch first (pytorch.org). Cairo-TTS runs on the CPU by default; pass device="cuda" (or --device cuda) to use the GPU, or device="auto" to pick it when available.
  • CPU only: pip install torch --index-url https://download.pytorch.org/whl/cpu keeps the install small.

🐍 Python

from cairo_tts import CairoTTS

tts = CairoTTS.from_pretrained(
    "mohammedaly22/Cairo-TTS",   # or a local folder
    device="cpu",                # "cpu" (default) | "cuda" | "cuda:1" | "auto"
    max_prompt_sec=10,           # seconds of reference audio used for cloning
    quantize=False,              # int8 weights on CPU
    num_threads=None,            # CPU threads
)

# 1) generate: a float32 numpy array at 24 kHz
audio = tts.generate("النهارده الجو حلو اوي, ايه رأيك ننزل نتمشى شوية؟")

# 2) save straight to a file, with a preset voice
tts.save("عارف ايه اكتر حاجة بتخوفني.", "ahmed.wav", voice="ahmed")

# 3) clone any voice (zero-shot) from a short, clean recording
tts.save("ده صوتي انا, بس الموديل هو اللي بيتكلم.", "me.wav", voice="my_voice.wav")
tts.export_voice("my_voice.wav", "my_voice.safetensors")    # instant to reload: voice="my_voice.safetensors"

# 4) stream: chunks arrive while audio is generated
for chunk in tts.stream("حاسس اني واقف مكاني. كل يوم نفس التاسكات, نفس ال meetings.", voice="sara"):
    play(chunk)                                              # your audio sink

# 5) metrics of the last call
m = tts.last_metrics
print(f"TTFA {m.ttfa*1000:.0f} ms · {m.audio:.1f}s audio in {m.total:.2f}s · {m.x_realtime:.1f}x real time · {m.device}")

# 6) see exactly what the model reads
print(tts.normalize("كلمني على 01012345678 الساعة 3:30 م"))
List the preset voices
for v in tts.voices():
    print(v["id"], v["name_ar"], v["gender"], v["description_ar"])
Male Female
mohamed محمد sara سارة
ahmed أحمد mariam مريم
ali علي nour نور
omar عمر fatma فاطمة
youssef يوسف heba هبة
mostafa مصطفى yasmin ياسمين
karim كريم mona منى
hassan حسن rana رنا
tarek طارق dina دينا
yehia يحيى malak ملك

Each voice has an Arabic and an English description (pitch, style, tone) in voices/voices.json. tarek is the default voice (used when voice is not given). The names are made up.

A complete script is in examples/infer.py.

Command line

cairo-tts say "ال meeting اتأجل لبكره." -o out.wav --voice ahmed
cairo-tts say "صوتي انا." -o me.wav --voice my_voice.wav --device cpu
echo "النص من ملف" | cairo-tts say - -o out.wav
cairo-tts voices                     # preset voices
cairo-tts normalize "الساعة 3:30 م"   # → الساعة تلاتة ونص العصر
cairo-tts serve --port 8000          # web studio

🎛️ Web studio

pip install "cairo-tts[ui]"
cairo-tts serve                       # http://127.0.0.1:8000   (--device cpu|cuda, --host 0.0.0.0)
  • Two modes: توليد كامل (generate the whole clip) and بث مباشر (live streaming, played while it is generated).
  • Voices: a searchable dropdown of the 20 presets (descriptions, play/pause previews), or استنسخ صوت (clone a voice): upload a file or record from the microphone.
  • Parameters: temperature, LSD steps, EOS threshold, frames after EOS, noise clamp, chunk size.
  • Metrics after every run: server TTFA, browser TTFA, total time, audio length, × real time, RTF, chunks / characters, device.
  • Pronunciation toolbar (فتحة، ضمة، كسرة، سكون، شدة، ةْ، ~), a random Egyptian sentence button, and a preview of the normalized text.
  • A minimal Arabic, RTL, responsive layout with dark and light themes (?theme=light|dark), a waveform that fills in while streaming, and a generation history.
  • Streaming plays through an AudioWorklet at the model's 24 kHz rate with a short pre-buffer, so chunks join without gaps or resampling clicks.
  • A JSON API at /api/docs: POST /api/generate, POST /api/stream (NDJSON PCM chunks), GET /api/voices, POST /api/voices/upload, POST /api/normalize.

Use it from Python (e.g. in your own app):

from cairo_tts import CairoTTS
from cairo_tts.server import create_app, serve

serve(CairoTTS.from_pretrained(device="cuda"), host="0.0.0.0", port=8000)
# or: app = create_app(tts)  →  mount / run with any ASGI server

📓 Colab notebooks

Notebook
Quick start: load, preset voices, cloning, streaming, preprocessing, diacritics, parameters 01_quickstart.ipynb Open in Colab
Web UI: the full studio inside Colab, no local install 02_web_ui.ipynb Open in Colab

Both download the public model from Hugging Face; no token is needed.

🤗 Hugging Face Space

The Space runs the same studio (Docker SDK, port 7860). To deploy your own:

python scripts/deploy_space.py --space <user>/Cairo-TTS --token-secret   # uploads space/ + the package source

--token-secret stores your token as the Space's HF_TOKEN secret (only needed if you point it at a private model). Optional Space variables: CAIRO_TTS_MODEL, CAIRO_TTS_DEVICE, CAIRO_TTS_QUANTIZE=1.

✍️ Pronunciation control

The model adds diacritics on its own. Write them yourself only where it reads a word wrong:

Write Meaning Example
ةْ (ta marbuta + sukun) ة is pronounced t, as in the construct state (إضافة); normalized to تْ عربيةْ ابويا → ʿarabiyyit abūya; plain عربية → ʿarabiyya
~ after a letter the Egyptian reading of that letter, mainly ق → glottal stop (ء) ق~لبي → ʾalbi, ق~ولتلك → ʾultilak
a vowel (َ ُ ِ) chooses between readings نِفسَها (she wants) vs نَفسَها (herself)
shadda ّ doubles the consonant بَتمَشَّى
sukun ْ no vowel اتْحَرَجْت
Latin letters English words ال meeting, ال deal
CEO, AI upper-case runs are spelled as English letters → c e o, a i (write ceo to read it as a word)
. , ، sentence end (long pause) / short pause; ? ! become .

Order of marks: letter → ~ → shadda → vowel (e.g. ق~َ). The frontend also reorders them for you. ~ is the marker the model learned from CATT's Egyptian «؞» sign.

ملاحظات بالمصري
  • اكتب زي ما بتتكلم: «مش عارف»، «عشان كدة»، «إزيك». الفصحى بتشتغل بس العامية أحلى.
  • الكلام الإنجليزي اكتبه بالحروف اللاتيني: «ال meeting»، «ال deadline».
  • لو كلمة اتقرت غلط شكّلها بس هي: «نِفسَها» بدل «نفسها».
  • ةْ: التاء المربوطة اللي عليها سكون بتتنطق «ت»: «عربيةْ ابويا» ← عربيِّت أبويا.
  • ~: بعد الحرف معناها انطقه بالمصري، وأشهرها «ق~» تتقري همزة: «ق~لبي» ← ألبي.
  • الصوت المرجعي: ٨–١٠ ثواني نضيفة، صوت واحد، من غير مزيكا.
  • لو آخر الجملة بيتقطع نزّل «حد النهاية» (eos_threshold)، ولو الصوت مش ثابت قلل الحرارة.

🔢 Text preprocessing

preprocess_egyptian() runs before the model frontend. You can use it on its own:

from cairo_tts import preprocess_egyptian, prepare_text

preprocess_egyptian("كلمني على 01012345678 او ابعت على ahmed.ali@gmail.com")
# كلمني على زيرو واحد زيرو, واحد اتنين تلاتة اربعة, خمسة ستة سبعة تمانية, او ابعت على احمد دوت علي ات gmail دوت كوم

prepare_text("الاجتماع الساعة 3:30 م و السعر 250 جنيه بخصم 15%")[0]
# الاجتماع الساعة تلاتة ونص العصر و السعر ميتين وخمسين جنية بخصم خمستاشر في المية
Input Spoken
01012345678, +20 10 … phone digits grouped 3-4-4: «زيرو واحد زيرو, …», «زائد اتنين زيرو …»
ahmed.ali@gmail.com «احمد دوت علي ات gmail دوت كوم» (Arabic names typed in Latin letters are written in Arabic)
www.youtube.com, https://… «w w w دوت youtube دوت كوم»
3:30 م, 9:15, 10:45 pm «تلاتة ونص العصر», «تسعة وربع», «حداشر الا ربع بالليل»
15/3/1998 «خمستاشر مارس سنة الف وتسعمية وتمانية وتسعين»
250 جنيه, $99, 50 EGP, 1.5 € Egyptian amounts with currency names
15%, 3.5 «خمستاشر في المية», «تلاتة فاصلة خمسة»
5K, 2M, 3Bn «خمسة الف», «اتنين مليون», «تلاتة مليار»
120 km/h, 5 kg, 64 GB units in Arabic
د/ احمد, م/, ش., ج.م.ع «دكتور», «مهندس», «شارع», «جمهورية مصر العربية»
CEO, #مصر, @user, & «c e o», «هاشتاج مصر», «user», «و»

Numbers are verbalized in Egyptian (1994 → «الف وتسعمية واربعة وتسعين»). Runs of more than 9 digits are read digit by digit.

⚙️ Parameters

Parameter Default
voice default voice preset id, an audio file (cloning), or an exported .safetensors
temperature 0.3 lower is steadier; higher is more expressive and less stable
lsd_steps 1 flow decoding steps per 80 ms frame
eos_threshold -4.0 end-of-speech threshold: higher stops earlier, lower if the last word gets cut
noise_clamp None clamps the sampling noise (e.g. 2.0)
frames_after_eos auto 80 ms frames kept after the end of speech
max_letters 160 long text is split at . then , into chunks of this many letters
stop None a threading.Event that stops streaming early

📊 Speed

Measured with this package after warm-up, on 7–11 s sentences:

Device Time to first audio Throughput
NVIDIA GTX 1660 Ti (6 GB) ~80 ms ~2.2× real time
Intel i7-10750H laptop CPU ~330 ms ~2.6× real time

🧠 Model

The model is a Pocket TTS (Kyutai) architecture: a causal transformer over Mimi latents with a 1-step flow head and a streaming Mimi decoder (24 kHz).

  • A 24-layer teacher was fine-tuned on ~747 h of Egyptian podcasts collected with the EgySpeech pipeline, then distilled into this 6-layer student.
  • Details are on the model card.

🗂️ Repository

src/cairo_tts/
├── model.py            CairoTTS: loading, devices, voices, generate / stream / save, metrics
├── text/               Egyptian preprocessing + the training frontend (numbers, diacritics, ta marbuta)
├── server/             FastAPI app + static web studio (HTML / CSS / JS)
└── cli.py              cairo-tts say | serve | voices | normalize
notebooks/              Colab quick start + web UI
examples/infer.py       minimal script
space/                  Hugging Face Space (Docker)
scripts/                prepare_voices.py · upload_to_hub.py · deploy_space.py
tests/                  text + inference + API tests (pytest)

⚖️ Responsible use

Cairo-TTS can imitate voices.

  • Do not use it to impersonate anyone without their consent, to deceive, or to commit fraud.
  • The preset voices are short clips of podcast speakers and are provided for research and demos only.
  • Label synthetic audio when you publish it.

📜 License

  • The code is MIT.
  • The model weights are fine-tuned from Kyutai's Pocket TTS and follow its terms. See NOTICE.md and the model card.

Metadata

Release files for cairo-tts 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cairo-tts 0.1.0
File Size Uploaded
cairo_tts-0.1.0.tar.gz 138.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cairo-tts 0.1.0
File Interpreter ABI Platform
cairo_tts-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 274.6 kB

Release files / cairo_tts-0.1.0.tar.gz

Download URL cairo_tts-0.1.0.tar.gz
Size 138.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e87247a7a4abd557e6678fd2eff8e04d343e82e5175d98e992dc7b654f24a9c6
BLAKE2b-256 checksum
How to use checksums
69cf55c78db82571e4ddfa55081190aeb6a14b7db7857aaa906f3b8ae05779d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / cairo_tts-0.1.0-py3-none-any.whl

Download URL cairo_tts-0.1.0-py3-none-any.whl
Size 136.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19754e38f7a2f48d7775acc29859cbd7bca8b7c8dda3f50102c572bf8cc31e1a
BLAKE2b-256 checksum
How to use checksums
f31d1986e4616d85cdfd9b7f23ece9e951282ca3781f6719c4943dfcbdbd5a7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release 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