python text to speech api tutorial: build a speech app with rumik silk

python text to speech api tutorial: build a speech app with rumik silk

python text to speech api tutorial: build a speech app with rumik silk

published

published

people don't always want to read everything on a screen. customers may need to hear an order update, employees may need narration for a training course, or a caller may be waiting for an answer from a voice agent. text to speech makes those experiences possible, whether the audio is prepared in advance as a voiceover or generated during a conversation.

in this tutorial, we'll build a python app using rumik silk text to speech models. we'll cover saving audio, choosing a voice and speaking style, and playing speech as it streams. the examples use english and the rumik python sdk, with the setup and playback code included.

install the sdk and connect your rumik account

we'll use python with the rumik python sdk handling the requests to silk. if you're adding this to an existing python project, this is the dependency it needs:

python -m
python -m

you'll see rumik-ai in the install command and rumikai in the imports. they're the package and module names for the same sdk. we're using version 1.0.0 in these examples.

the app also needs an api key from the rumik playground, where you can create one under api keys. we'll keep it out of the python file by making it available through the terminal:

rumik playground api keys page showing the option to create a key, with existing key values hidden

windows powershell

$env:RUMIK_API_KEY = "your_api_key"
$env:RUMIK_API_KEY = "your_api_key"

mac or linux

export RUMIK_API_KEY="your_api_key"
export RUMIK_API_KEY="your_api_key"

note: your actual key goes in place of your_api_key. the sdk picks up RUMIK_API_KEY automatically from this terminal session. on machines where python is installed as python3, that command works in place of python throughout the examples.

convert text to speech and save it as a wav file

our first input is an order update. we'll ask rumik silk for a steady, professional read and save the result as order-update.wav, ready to open in an audio player.

the request and file save sit together in our first script, generate_speech.py:

from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 1 PM."


def main():
    with Rumik() as client:
        audio = client.speech.create(
            text=TEXT,
            model="mulberry",
            speaker="emma",
            description="a calm female voice with an american accent and steady pacing, like a customer support agent",
        )
        audio.save("order-update.wav")

    print("Saved order-update.wav")


if __name__ == "__main__":
    main()
from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 1 PM."


def main():
    with Rumik() as client:
        audio = client.speech.create(
            text=TEXT,
            model="mulberry",
            speaker="emma",
            description="a calm female voice with an american accent and steady pacing, like a customer support agent",
        )
        audio.save("order-update.wav")

    print("Saved order-update.wav")


if __name__ == "__main__":
    main()

here's what we're sending in that request:

  • text: the content the app needs to say.

  • model: mulberry, the api value for silk mulberry 1.5.

  • speaker: emma, the named voice selected for our english order update.

  • description: the accent, pace, and delivery you're asking for.

we're using silk mulberry 1.5 with the emma voice preset. the model value in the request is mulberry.

the terminal where we set the key already has what the sdk needs. from there, we can run:

once the request succeeds, you'll find order-update.wav beside the script. opening that file in an audio player lets you hear the update. saving and playback are separate here, which gives you a file to review or reuse.

here's how the order update sounds with emma:

TEXT is where your own content will go. each run makes a new synthesis request and replaces the same file. a different output filename lets you keep earlier versions for comparison.

note: mulberry 1.5 accepts up to 2,000 characters of text per request. longer scripts need to be split before they are sent to the api.

set the speaker, accent, and pace

the order update currently asks for a steady delivery. for a different script, you might want a slower read. the request keeps the speaker and delivery separate, so we can adjust either:

  • speaker selects a named voice. we're using emma. other named voices include siya, ira, and noah.

  • description guides the delivery. this is where we ask for an accent, pace, and tone in plain language. it stays in the request even when we choose a named speaker.

we can ask for a diffrent version of the order update with this description inside client.speech.create():

description="a male 40s british voice, low pitch, gravelly timbre, neutral, formal register, like a dramatic narrator."
description="a male 40s british voice, low pitch, gravelly timbre, neutral, formal register, like a dramatic narrator."

running generate_speech.py again gives us another version to listen to. keeping the text and speaker fixed makes the pace comparison clearer. if it's the voice itself you want to change, the speaker field is the next thing to try.

for e-learning, a passage with the actual names, dates, and numbers gives you something representative to listen to before generating the full script.

stream text to speech from python to your speakers

the saved file gives us something to review or reuse. for spoken responses, we can also have the app play audio as it arrives. that needs a connection to silk and a player on our computer.

we'll add the sdk's websocket support and sounddevice for playback:

python -m pip install "rumik-ai[ws]" "sounddevice"
python -m pip install "rumik-ai[ws]" "sounddevice"
  • rumik-ai[ws] adds the websocket support used by the sdk.

  • sounddevice sends audio to your computer's output device. on linux, it may also need the portaudio system library, covered in the installation guide.

the audio arrives as 24 khz, mono, signed 16-bit pcm. the chunks don't carry a wav header, so the player needs the sample rate, channel count, and sample format set explicitly.

our second script, stream_speech.py, connects those pieces:

import sounddevice as sd
from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 3 PM."


def main():
    with Rumik() as client:
        with sd.RawOutputStream(
            samplerate=24000,
            channels=1,
            dtype="int16",
        ) as player:
            with client.speech.stream(
                text=TEXT,
                model="mulberry",
                speaker="emma",
                description="a calm female voice with an american accent and steady pacing, like a customer support agent",
            ) as stream:
                pending = b""
                played_audio = False

                for chunk in stream:
                    pending += chunk
                    complete_bytes = len(pending) - (len(pending) % 2)

                    if complete_bytes:
                        player.write(pending[:complete_bytes])
                        pending = pending[complete_bytes:]
                        played_audio = True

                if pending:
                    raise RuntimeError("The stream ended with an incomplete audio sample.")
                if not played_audio:
                    raise RuntimeError("The stream returned no audio.")

    print("Playback finished.")


if __name__ == "__main__":
    main()
import sounddevice as sd
from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 3 PM."


def main():
    with Rumik() as client:
        with sd.RawOutputStream(
            samplerate=24000,
            channels=1,
            dtype="int16",
        ) as player:
            with client.speech.stream(
                text=TEXT,
                model="mulberry",
                speaker="emma",
                description="a calm female voice with an american accent and steady pacing, like a customer support agent",
            ) as stream:
                pending = b""
                played_audio = False

                for chunk in stream:
                    pending += chunk
                    complete_bytes = len(pending) - (len(pending) % 2)

                    if complete_bytes:
                        player.write(pending[:complete_bytes])
                        pending = pending[complete_bytes:]
                        played_audio = True

                if pending:
                    raise RuntimeError("The stream ended with an incomplete audio sample.")
                if not played_audio:
                    raise RuntimeError("The stream returned no audio.")

    print("Playback finished.")


if __name__ == "__main__":
    main()

here's where the audio goes:

  • client.speech.stream() receives chunks from silk.

  • player.write() passes complete samples to the speakers through sounddevice's raw audio output.

  • pending keeps a leftover byte when a chunk ends partway through a two-byte sample.

the with blocks close the connections and audio device when the script finishes or fails. if you found a speaker and description you prefer in the previous example, the same settings belong in this request too.

we can run this from the same terminal as the first script:

after a successful request, you should hear the order update as the audio arrives. the player uses your computer's default output, so there's no saved file to open this time.

if you can't hear audio: python -m sounddevice lists the available devices. the output device and volume are the first things to check. a different output can be selected with device=... in sd.RawOutputStream(), using the numeric id from that list.

note: we're sending the complete text at the start and streaming the generated audio back. this example doesn't feed text word by word from an llm. playback also needs a computer with speakers or headphones, which a remote server may not have.

take your python speech app beyond the example

your app already has the text: an order update, a training lesson, or a reply to a customer. with the connection to rumik silk in place, those inputs can use the voice settings and audio handling we've built here.

a saved wav works when your team needs to review or reuse the audio. streaming fits responses that need to play as they're generated. whichever path you use, the most useful next test is your own content, with the names, numbers, and phrasing your users will hear.

people don't always want to read everything on a screen. customers may need to hear an order update, employees may need narration for a training course, or a caller may be waiting for an answer from a voice agent. text to speech makes those experiences possible, whether the audio is prepared in advance as a voiceover or generated during a conversation.

in this tutorial, we'll build a python app using rumik silk text to speech models. we'll cover saving audio, choosing a voice and speaking style, and playing speech as it streams. the examples use english and the rumik python sdk, with the setup and playback code included.

install the sdk and connect your rumik account

we'll use python with the rumik python sdk handling the requests to silk. if you're adding this to an existing python project, this is the dependency it needs:

python -m

you'll see rumik-ai in the install command and rumikai in the imports. they're the package and module names for the same sdk. we're using version 1.0.0 in these examples.

the app also needs an api key from the rumik playground, where you can create one under api keys. we'll keep it out of the python file by making it available through the terminal:

rumik playground api keys page showing the option to create a key, with existing key values hidden

windows powershell

$env:RUMIK_API_KEY = "your_api_key"

mac or linux

export RUMIK_API_KEY="your_api_key"

note: your actual key goes in place of your_api_key. the sdk picks up RUMIK_API_KEY automatically from this terminal session. on machines where python is installed as python3, that command works in place of python throughout the examples.

convert text to speech and save it as a wav file

our first input is an order update. we'll ask rumik silk for a steady, professional read and save the result as order-update.wav, ready to open in an audio player.

the request and file save sit together in our first script, generate_speech.py:

from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 1 PM."


def main():
    with Rumik() as client:
        audio = client.speech.create(
            text=TEXT,
            model="mulberry",
            speaker="emma",
            description="a calm female voice with an american accent and steady pacing, like a customer support agent",
        )
        audio.save("order-update.wav")

    print("Saved order-update.wav")


if __name__ == "__main__":
    main()

here's what we're sending in that request:

  • text: the content the app needs to say.

  • model: mulberry, the api value for silk mulberry 1.5.

  • speaker: emma, the named voice selected for our english order update.

  • description: the accent, pace, and delivery you're asking for.

we're using silk mulberry 1.5 with the emma voice preset. the model value in the request is mulberry.

the terminal where we set the key already has what the sdk needs. from there, we can run:

once the request succeeds, you'll find order-update.wav beside the script. opening that file in an audio player lets you hear the update. saving and playback are separate here, which gives you a file to review or reuse.

here's how the order update sounds with emma:

TEXT is where your own content will go. each run makes a new synthesis request and replaces the same file. a different output filename lets you keep earlier versions for comparison.

note: mulberry 1.5 accepts up to 2,000 characters of text per request. longer scripts need to be split before they are sent to the api.

set the speaker, accent, and pace

the order update currently asks for a steady delivery. for a different script, you might want a slower read. the request keeps the speaker and delivery separate, so we can adjust either:

  • speaker selects a named voice. we're using emma. other named voices include siya, ira, and noah.

  • description guides the delivery. this is where we ask for an accent, pace, and tone in plain language. it stays in the request even when we choose a named speaker.

we can ask for a diffrent version of the order update with this description inside client.speech.create():

description="a male 40s british voice, low pitch, gravelly timbre, neutral, formal register, like a dramatic narrator."

running generate_speech.py again gives us another version to listen to. keeping the text and speaker fixed makes the pace comparison clearer. if it's the voice itself you want to change, the speaker field is the next thing to try.

for e-learning, a passage with the actual names, dates, and numbers gives you something representative to listen to before generating the full script.

stream text to speech from python to your speakers

the saved file gives us something to review or reuse. for spoken responses, we can also have the app play audio as it arrives. that needs a connection to silk and a player on our computer.

we'll add the sdk's websocket support and sounddevice for playback:

python -m pip install "rumik-ai[ws]" "sounddevice"
  • rumik-ai[ws] adds the websocket support used by the sdk.

  • sounddevice sends audio to your computer's output device. on linux, it may also need the portaudio system library, covered in the installation guide.

the audio arrives as 24 khz, mono, signed 16-bit pcm. the chunks don't carry a wav header, so the player needs the sample rate, channel count, and sample format set explicitly.

our second script, stream_speech.py, connects those pieces:

import sounddevice as sd
from rumikai import Rumik

TEXT = "Your order is confirmed. Delivery is scheduled for Friday at 3 PM."


def main():
    with Rumik() as client:
        with sd.RawOutputStream(
            samplerate=24000,
            channels=1,
            dtype="int16",
        ) as player:
            with client.speech.stream(
                text=TEXT,
                model="mulberry",
                speaker="emma",
                description="a calm female voice with an american accent and steady pacing, like a customer support agent",
            ) as stream:
                pending = b""
                played_audio = False

                for chunk in stream:
                    pending += chunk
                    complete_bytes = len(pending) - (len(pending) % 2)

                    if complete_bytes:
                        player.write(pending[:complete_bytes])
                        pending = pending[complete_bytes:]
                        played_audio = True

                if pending:
                    raise RuntimeError("The stream ended with an incomplete audio sample.")
                if not played_audio:
                    raise RuntimeError("The stream returned no audio.")

    print("Playback finished.")


if __name__ == "__main__":
    main()

here's where the audio goes:

  • client.speech.stream() receives chunks from silk.

  • player.write() passes complete samples to the speakers through sounddevice's raw audio output.

  • pending keeps a leftover byte when a chunk ends partway through a two-byte sample.

the with blocks close the connections and audio device when the script finishes or fails. if you found a speaker and description you prefer in the previous example, the same settings belong in this request too.

we can run this from the same terminal as the first script:

after a successful request, you should hear the order update as the audio arrives. the player uses your computer's default output, so there's no saved file to open this time.

if you can't hear audio: python -m sounddevice lists the available devices. the output device and volume are the first things to check. a different output can be selected with device=... in sd.RawOutputStream(), using the numeric id from that list.

note: we're sending the complete text at the start and streaming the generated audio back. this example doesn't feed text word by word from an llm. playback also needs a computer with speakers or headphones, which a remote server may not have.

take your python speech app beyond the example

your app already has the text: an order update, a training lesson, or a reply to a customer. with the connection to rumik silk in place, those inputs can use the voice settings and audio handling we've built here.

a saved wav works when your team needs to review or reuse the audio. streaming fits responses that need to play as they're generated. whichever path you use, the most useful next test is your own content, with the names, numbers, and phrasing your users will hear.

frequently asked questions

frequently asked questions

frequently asked questions

yes. rumik silk turns text from your python app into speech. the rumik python sdk handles the api requests, and your app can save the audio as a wav file or play it as it streams. you can also choose a voice and describe its accent, pace, and tone.
to use rumik silk in python, `python -m pip install rumik-ai` adds the sdk to your project. streaming playback also needs `python -m pip install "rumik-ai[ws]" sounddevice`. the speech model runs on rumik's service, while the sdk connects your python app to it.
rumik silk offers free credits to try its text to speech api. that gives you a way to test speech generation before paying for further usage. once the trial credit is used, continued api usage is paid.
rumik silk can provide the spoken output in your python voice app. an stt service first converts the user's speech into text. your app processes it and prepares a response, which rumik silk then turns into speech.
yes. rumik silk uses ai speech models, including silk mulberry 1.5, to generate audio from text. you can choose a named voice and describe the delivery you want, and the model uses those inputs to guide the generated speech.
for narration and streamed replies, we're using rumik silk mulberry 1.5. it accepts a voice description and an optional named speaker. rumik silk muga 1 suits short, expressive lines where you want tone tags such as [happy] or vocal events such as <laugh>.
rumik silk’s unlimited tts plans start at $199/month for 1 concurrent request, with plans for 2 at $399, 4 at $799, and 8 at $1,599/month, all in usd. each plan includes unlimited speech generation, with concurrency shared across your account.

read other articles

read other articles

read other articles