Model or dataset
KoljaB/RealtimeTTS avatar
KoljaB/RealtimeTTS

RealtimeTTS: streaming text to speech in Python with fallback engines

Converts text to speech in realtime

4,026 stars406 forksPythonMIT

At a glance

What is it?
RealtimeTTS is an MIT-licensed Python library that turns strings, generators and LLM token streams into audio with low latency. Its engine matrix is unusually wide, but the recommended Qwen path only ships validated wheels for x86-64 Windows and Linux.
Who is it for?
Adopt RealtimeTTS if you are building a Python voice loop that consumes streamed model output and you want one API over several engines, with fallback when a provider fails. Skip it if you need a mobile SDK, a GUI, or a single cloud voice you can call directly without an abstraction layer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap RealtimeTTS fills between an LLM token stream and a speaker

Most text-to-speech libraries assume you already have a finished string. RealtimeTTS assumes the opposite: text arrives in fragments, and the user should hear the first sentence while the rest is still being generated. The README states that the library turns "strings, generators, and LLM token streams into audio with low latency", and that framing defines the audience. If you are wiring an LLM into a voice interface, the hard part is not synthesis quality, it is deciding when a partial token stream has become a speakable unit and keeping playback ahead of generation. RealtimeTTS delegates that decision to stream2sentence, which the requirements file describes as "the core of RealtimeTTS - it quickly converts streamed text into sentences for real-time synthesis". The library then owns playback, buffering, cancellation and engine failover. The intended user is a Python developer building a conversational agent, a screen reader, a narration tool, or a telephony bot, who wants to swap engines without rewriting the audio plumbing. It is not a desktop application, and it is not a hosted service.

How feed, play and the engine layer fit together

The architecture is deliberately thin. A TextToAudioStream wraps an engine instance. You call feed() with either a string or an iterator, and you call play() to start playback. Internally, text is accumulated and split into sentences before being handed to the engine, which is why a generator works as well as a string: the splitter can emit a complete sentence as soon as one exists, without waiting for the stream to end. The engine layer is where the variation lives. The README's engine table lists local system voices, cloud APIs, free service wrappers, local neural models and voice-cloning stacks behind that one interface. Because each engine is a separate extra, the install surface is modular: setup.py enumerates extras including system, azure, elevenlabs, openai, gtts, edge, coqui, camb, minimax, cartesia, modelslab, orpheus, qwen, qwen-server, omnivoice, luxtts, chatterbox, inflect, sopro and more. The README also documents fallback engines, so a failed provider can hand off to another one rather than dropping audio. Callbacks cover text, audio, sentence, character, word timing and audio chunks, which is how you would drive captions or a waveform display from the same stream. Sync and async playback both exist, with pause, resume, stop and state inspection.

Installing RealtimeTTS and getting first audio out of SystemEngine

The README recommends the system engine for the fastest local smoke test because it needs no API key and no model download. Install the extra, and on Linux install the PortAudio headers first, since the traditional engine extras use PyAudio.

bash
sudo apt-get update
sudo apt-get install python3-dev portaudio19-dev

On macOS the equivalent prerequisite is Homebrew's portaudio formula.

bash
brew install portaudio

With the native dependency in place, install the extra itself.

bash
pip install "realtimetts[system]"

The README gives this first program. Keep the __main__ guard, which the documentation calls out especially for Windows and for engines that start worker processes.

python
from RealtimeTTS import TextToAudioStream, SystemEngine


if __name__ == "__main__":
    stream = TextToAudioStream(SystemEngine())
    stream.feed("Hello from RealtimeTTS.")
    stream.play()

You should hear the sentence through your default output device. The more interesting test is streaming, where feed() receives a generator and playback begins before the second chunk exists.

python
def text_chunks():
    yield "This starts speaking quickly. "
    yield "More text can arrive while audio is already playing."

Pass text_chunks() to feed() instead of a string, then call play() as before. To keep the audio but skip the speaker, the README shows play(output_wavfile="speech.wav", muted=True), which writes a WAV file instead of playing it.

QwenEngine is the recommended path, and it is platform-narrow

The README is explicit that QwenEngine is "currently the recommended and preferred RealtimeTTS engine" for supported Windows and Linux systems with an NVIDIA GPU, citing multilingual Qwen3-TTS quality, x-vector and ICL voice cloning, native 24 kHz PCM streaming and fast cancellation. The install pins a native wheel through a binary-only flag.

bash
python -m pip install --only-binary=realtimetts-qwen-native "realtimetts[qwen]"
python -m qwentts_cpp doctor

The doctor subcommand is the right first step, because the constraint is real: the README states that RealtimeTTS 0.7.4 declares validated native Qwen wheels only for x86-64 Windows and Linux, and that macOS and other platforms are not supported release targets. The wheel does not require a local CUDA Toolkit, which removes one common source of setup pain, but it does not remove the architecture limit. The README also quotes orientation figures from the maintainers' own tuned RTX 4090 runs: roughly 35 ms engine time to first token, another 35 ms before RealtimeTTS emits its first PCM chunk, about 10 ms of silence inside that chunk, predicted audible onset of 80.9 ms and RTF of 0.108. Treat those as the project's numbers on its own hardware, not a promise for yours; the README itself says to measure the complete path on your target system. If you are on a Mac, an ARM server, or a machine without an NVIDIA GPU, the documented lightweight alternative is InflectEngine, described as one fixed English voice on CUDA or ONNX CPU.

Where RealtimeTTS is the wrong choice

The first limitation is packaging, not capability. Because every engine is an optional extra, the dependency graph you get depends entirely on which extras you name, and requirements.txt shows how heavy the full set is: torch, torchaudio, librosa, phonemizer, espeakng-loader, huggingface-hub, safetensors and more, all shared across the neural engines. Installing realtimetts[all] pulls a large amount of that in. The second is the platform boundary already described for the native Qwen wheels. The third is that this is a library, not a product: there is no mobile SDK, and the related-search interest in an Android build has no counterpart in the repository, whose top-level entries are Python packaging, docs, tests, examples and Docker files. The fourth is the sentence-splitting dependency. The README notes that splitting defaults to stream2sentence's nltk+rule-based consensus mode, that the normal install brings in stream2sentence[nltk] but not Stanza or PyTorch, and that Stanza is a separate extra. If your language or your text needs a stronger sentence boundary model, that is an extra install and an extra failure mode, and the README does not document what happens when the splitter is wrong about a boundary. Finally, if you need exactly one cloud voice and nothing else, the abstraction costs you a layer of indirection without buying you anything.

RealtimeTTS versus calling a cloud TTS API directly

The honest alternative is the direct route: call a provider's own SDK, or run a local synthesis server, and manage buffering yourself. ElevenLabs appears both in the related searches and as an installable extra, and the difference in approach is instructive. Calling the provider directly gives you that vendor's full parameter surface, their voice library, and their own streaming semantics, with one dependency and one set of credentials. RealtimeTTS instead gives you a uniform interface and, more importantly, the option to change your mind. Fallback engines mean a provider outage degrades to a second engine rather than to silence, and voice switching plus voice-cloning workflows are exposed through the same stream object where the underlying engine supports them. The cost is that engine-specific features are only reachable to the extent the wrapper exposes them, and you inherit the library's release cadence for fixes. A middle option exists in the repository itself: the qwen-server extra exposes the same native engine through an OpenAI-compatible HTTP API with /v1/audio/speech, dynamic voice registration, persistent voice latents and request and stall metrics on /health. That server is headless and does not install PyAudio or PortAudio, so it is the cleaner choice when synthesis and playback live on different machines. Note the security defaults the README states: the server binds to loopback at 127.0.0.1, LAN exposure needs a deliberate --allow-lan bind plus a built-in API key or a trusted reverse proxy terminating TLS, and CORS defaults to explicit localhost origins and rejects wildcard, since CORS is not an access control boundary.

Maintenance cadence, licence and the addendum you should read

The repository is not archived and the last push was on 2026-08-31, with releases v0.8.2, v0.8.3 and v0.8.5 landing within the final days of that month. That is a fast release rhythm, and it cuts both ways: you get fixes quickly, and you also get churn in an API surface that spans a dozen optional engines. Pinning a version is the sensible default for anything you ship. The project is MIT licensed, which is permissive for the library code, but the repository also carries a LICENSING_ADDENDUM.md at the top level. That file exists precisely because the library wraps third-party engines, model weights and voice assets whose terms are not the library's to grant. If you plan to redistribute a product that includes cloned voices or bundled model weights, read the addendum alongside the terms of the specific engine you selected; the README points to the Qwen guide for licensing and asset boundaries. Upgrading also means re-checking the native wheel pins, since requirements.txt pins realtimetts-qwen-native[cuda12]==0.2.0 for win32 and linux, and a version bump there can change which platforms are supported. Nothing in the repository suggests an automatic migration path between engine extras, so treat an engine swap as a code change with a test plan, not a config toggle.

Editorial conclusion

Adopt RealtimeTTS if you are building a Python voice loop that consumes streamed model output and you want one API over several engines, with fallback when a provider fails. Skip it if you need a mobile SDK, a GUI, or a single cloud voice you can call directly without an abstraction layer. Before committing, verify three things on your own hardware: that your platform has a validated native wheel for the engine you want, that PortAudio is present if you use the PyAudio-backed extras, and how the LICENSING_ADDENDUM.md interacts with the engine and voice assets you plan to ship.

Frequently asked questions

What is RealtimeTTS?

It is a Python text-to-speech library for applications that need to turn strings, generators and LLM token streams into audio with low latency. It supports local system voices, cloud APIs, free service wrappers, local neural models and voice-cloning stacks behind one streaming interface.

What is the best TTS library for Python?

There is no single answer, and RealtimeTTS does not claim to be one. The README positions QwenEngine as its recommended engine for high-quality low-latency conversational speech on supported Windows and Linux systems with an NVIDIA GPU, and documents InflectEngine as the lightweight alternative for one fixed English voice.

Is RealtimeTTS open source?

Yes. The repository is licensed under MIT, and it is not archived. It also ships a LICENSING_ADDENDUM.md, because the third-party engines, model weights and voice assets it wraps carry their own terms.

How do I install RealtimeTTS?

Install the extra for the engine you want, for example pip install "realtimetts[system]" for the local smoke test. The traditional engine extras use PyAudio, so Linux needs python3-dev and portaudio19-dev and macOS needs the portaudio formula first.

Does RealtimeTTS run on macOS?

The library installs and the system engine works with PortAudio from Homebrew. The recommended QwenEngine is a different matter: the README states that validated native Qwen wheels exist only for x86-64 Windows and Linux, and that macOS is not a supported release target.

Official sources

  1. Issues
  2. KoljaB/RealtimeTTS on GitHub
  3. License: MIT
  4. README
  5. Releases
Community notes

Community notes