Skip to main content

SILMA TTS for Pipecat

A Pipecat text-to-speech integration for SILMA AI — English and Arabic speech synthesis, with Modern Standard Arabic and the Saudi (Najdi) dialect.

Maintained by SILMA AI. We build the TTS service this integration talks to, so it stays current with the API.

Tested with Pipecat v1.8.1.

Installation

uv add pipecat-silma
# or
pip install pipecat-silma

Prerequisites

An API key from app.silma.ai:

export SILMA_API_KEY="..."

Usage

from pipecat_silma import SilmaTTSService

tts = SilmaTTSService(
    api_key=os.environ["SILMA_API_KEY"],
    settings=SilmaTTSService.Settings(
        model="silma-tts-v2-english",
        voice="emma",
    ),
)

pipeline = Pipeline(
    [
        transport.input(),
        stt,
        user_aggregator,
        llm,
        tts,
        transport.output(),
        assistant_aggregator,
    ]
)

Models and voices

SILMA selects the language by model rather than by a language parameter. You can still pass a Pipecat Language, in settings or in a TTSUpdateSettingsFrame, and it will switch the model for you.

Model Language Voices
silma-tts-v2-english English james, emma
silma-tts-v2-msa Modern Standard Arabic sarah, salma, salwa, saja, sultan, salman, sulaiman, salim
silma-tts-v2-ksa Arabic, Saudi (Najdi) dialect same as MSA

Configuration

Constructor arguments, all also available on SilmaTTSService.Settings:

Parameter Default Description
api_key $SILMA_API_KEY Your SILMA API key
model silma-tts-v2-msa Model id, which also picks the language
voice sarah Pre-defined voice id
creativity server default Variance in speech prosody
speed server default Speed of the generated speech
user_id None Required for cloned voices and pronunciation overrides
custom_audio_id None Cloned voice id; requires user_id
enable_server_pronunciation_overrides False Apply account-level overrides; requires user_id
base_url https://api.silma.ai/tts/v2 API base URL
keepalive_interval_s 20.0 Ping interval for an idle connection; lower it if the proxy in front of the API has a shorter read timeout

creativity and speed are omitted from the request unless you set them, so SILMA's own defaults apply.

Settings can be changed while the pipeline runs, via Pipecat's TTSUpdateSettingsFrame:

await task.queue_frame(TTSUpdateSettingsFrame(settings=SilmaTTSService.Settings(voice="salma")))

Cloned voices

Upload a voice under Custom Voices at app.silma.ai/voices, then pass its id together with your user id:

SilmaTTSService(
    settings=SilmaTTSService.Settings(
        model="silma-tts-v2-ksa",
        voice="sarah",
        user_id="...",
        custom_audio_id="voice_1769817467123",
    ),
)

Pronunciation hints

SILMA reads phone numbers, emails and links correctly when they are tagged:

You can reach us on <STAG_PN>92005455</STAG_PN> or at <STAG_EMAIL>hi@silma.ai</STAG_EMAIL>.

The integration keeps these tags intact when it splits text, so a tag is never cut in half across two requests. Instruct your LLM to emit them — the example shows how.

Account-level pronunciation overrides configured at app.silma.ai/control apply when you pass user_id and enable_server_pronunciation_overrides=True.

Running the example

examples/foundational.py is a complete voice bot over a local WebRTC transport — no telephony account, no cloud room.

uv add pipecat-silma "pipecat-ai[webrtc,silero,openai,runner]"

export SILMA_API_KEY="..."
export OPENAI_API_KEY="..."

python examples/foundational.py

Open the URL it prints and start talking. For English:

LANGUAGE=en python examples/foundational.py

How it works

SilmaTTSService extends Pipecat's InterruptibleTTSService, which is the right base for a websocket service with no context id and no cancel message: the way to stop SILMA mid-utterance is to drop the socket and reconnect, and that base class does exactly that on an interruption.

Audio. SILMA returns a 24 kHz mono float32 waveform. The service converts it to the 16-bit PCM Pipecat carries in TTSAudioRawFrame, buffering samples that straddle a chunk boundary so a split never produces a click. Because the API takes no sample-rate parameter, the service pins its rate at 24000 and rejects a request for anything else rather than mislabelling the audio — let the output transport resample if your transport needs a different rate.

Text limits. The API caps a request at 250 characters, so a longer aggregation is split on word boundaries and sent as sequential requests over the same socket; their audio arrives in order and is concatenated into one context.

Connection. One websocket is held open and reused across turns, with a keepalive ping every keepalive_interval_s so an idle connection is not closed by the proxy in front of the API. On an interruption the socket is dropped and replaced — SILMA has no cancel message, so that is how speech stops promptly, including when the user talks over the very start of a reply. The replacement is not waited for: the old socket is detached at once and closed in the background, because Pipecat forwards the frame that stops playback only once the service's interruption handler returns.

Development

uv sync --extra dev
uv run pytest          # 40 tests, no API key or network needed
uv run ruff check .
uv run ruff format --check .

Two tests drive a real Pipecat pipeline to check barge-in behaviour, and Pipecat's sentence aggregator needs NLTK's sentence data for that. They skip themselves if the data is absent; to run them:

uv run python -c "import nltk; nltk.download('punkt_tab')"

License

BSD 2-Clause, matching Pipecat. See LICENSE.

Download files

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

Source Distribution

pipecat_silma-0.1.0.tar.gz (26.9 kB view details)

Uploaded Source

Built Distribution

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

pipecat_silma-0.1.0-py3-none-any.whl (17.2 kB view details)

Uploaded Python 3

File details

Details for the file pipecat_silma-0.1.0.tar.gz.

File metadata

  • Download URL: pipecat_silma-0.1.0.tar.gz
  • Upload date:
  • Size: 26.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pipecat_silma-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ec530a881e0b1ec73947a0b9f717d4548638530650782c646530534785d725db
MD5 4f1d130aa8c768e59be58a72c8157473
BLAKE2b-256 f71b95585d33f3f73a2cc9e8a076ec1c4634dab4ee94455a9fd4cc82e903f010

See more details on using hashes here.

File details

Details for the file pipecat_silma-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pipecat_silma-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pipecat_silma-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f960f6283b6b7445ac74bea7a4656c1f97bc06fb74fd71835a58dd4c3d51fa44
MD5 77e2ce18bce6fc058a2d98c61ecd0364
BLAKE2b-256 619a2ddf7e95292432dee6b4f55f238eeb9735bcfaa003ffb955b6c1d4c64293

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.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