Skip to main content

Palabra AI Python Client

Simple Python client for Palabra AI real-time streaming APIs: speech-to-speech translation, speech-to-text, and low-latency text-to-speech.

uv add palabra-ai          # or: pip install palabra-ai

Full API documentation: docs.palabra.ai.

Palabra has three separate streaming APIs, and the client mirrors that at the top level:

Product Entry point What it is
Realtime Speech-to-Speech Translation API palabra.translation(...) full pipeline translation API
Realtime Speech-to-Text API palabra.stt(...) transcription API: stream audio in, incremental text (and optional translations) out
Realtime TTS API palabra.tts(...) speech synthesis API: stream text in (e.g. from an LLM), audio out

Authentication, regions, errors and reconnection are shared by all three.

Authentication

Everything is driven by two values — an API Key and a region; all endpoints are derived from them automatically. Create your API Key on the Palabra API Keys page and set it via the environment or the constructor:

export PALABRA_API_KEY=...
export PALABRA_REGION=eu   # optional, defaults to "eu"
from palabra_ai import Palabra

palabra = Palabra()                            # reads the env vars
palabra = Palabra(api_key="...", region="eu")  # or explicit

The API Key authorizes the WebSocket connection directly: a streaming session is created server-side when you connect and cleaned up when the connection ends — there is nothing to manage.

Regions

Availability per region (more regions and endpoints are being added over time):

Region Speech-to-Speech Translation Speech-to-Text TTS
eu
us

Opening a stream for a product that is not available in the configured region raises ValueError with the list of regions where it is.


Speech-to-Speech Translation API

You continuously push audio chunks; Palabra streams back transcripts, translations, and synthesized speech.

Quick start

Audio comes from your source — a microphone, a VoIP call leg, a telephony bridge — anything that hands you PCM chunks. Push them into the session and consume events:

import asyncio
import time
from palabra_ai import Palabra, Transcript, Audio

CHUNK_MS = 320  # ~320 ms of PCM (s16le, 24 kHz, mono)

async def main():
    palabra = Palabra()

    async with palabra.translation(source="en", targets=["es"]) as session:

        async def send_audio():
            next_send = time.monotonic()
            while chunk := await audio_buffer.get():  # your audio source
                await session.send_audio(chunk)
                next_send += CHUNK_MS / 1000
                await asyncio.sleep(max(0, next_send - time.monotonic()))
            await session.end(eos_timeout=4)

        sender = asyncio.create_task(send_audio())

        async for event in session:
            match event:
                case Transcript():
                    print(event)
                case Audio():
                    play(event.pcm)

        await sender

asyncio.run(main())

async with palabra.translation(...) does everything for you: connects the WebSocket (your API Key authorizes it; a streaming session is created server-side automatically), sends the translation task, waits until the pipeline actually confirms it, and cleans up on exit.

Two rules for the input stream:

  1. Chunks must match the format declared in the task (default: PCM s16le, 24 kHz, mono; ~320 ms per chunk is optimal).
  2. Push at real-time rate — faster/slower pacing triggers ServerWarning (AUDIO_STREAM_TOO_FAST/TOO_SLOW/STALLED) and degrades quality. If your source is a live device or call, pacing comes for free.

WebRTC (browser / client-side apps)

This client uses WebSocket transport, which is the recommended option for server-side applications. For browser and mobile apps Palabra recommends the WebRTC transport with a JavaScript client: follow the WebRTC Quick Start, or start from the official TypeScript example. WebRTC handles microphone capture, pacing, jitter, etc. in the browser natively.

Events

Iterating the session yields typed events:

Event Fields Meaning
Transcript text, language, id, is_eos, is_translation partial/validated transcription & translation
Audio pcm, language, last_chunk, id TTS chunk (PCM s16le 24 kHz mono)
TaskInfo status, task response to get_task
StreamEnd end-of-stream confirmation after end(eos_timeout=...)
ServerError code, desc server-side error
ServerWarning code, message AUDIO_STREAM_TOO_FAST / TOO_SLOW / STALLED
Raw type, data anything else

Session control

await session.send_audio(chunk)                      # one raw chunk (pace it yourself)

await session.speak("Hola!", "es")                   # speak text into the stream (note: you must have this language as one of the target languages)
await session.speak("Hi all!", "en", translate=True) # translate to all targets first

await session.flush()                                # drop the current transcription and audio (interruption)
await session.pause();  await session.resume()       # pause and resume your session (stops billing)
await session.set_task(new_task)                     # change settings on the fly
await session.end(eos_timeout=4)                     # graceful finish: waits for the tail, emits StreamEnd

session.speak(text, lang) (the tts_task command) speaks through the translation pipeline and is unrelated to the standalone Realtime TTS API.

Settings

Common options are keyword arguments of translation(...); anything beyond that — build the task dict yourself:

from palabra_ai import build_task, Palabra

# common options inline
session = Palabra().translation(
    source="auto",
    targets=["es", "fr"],
    translate_partials=True,
    silence_threshold=0.8
)

# or full control, including per-target overrides and any server option
task = build_task(
    "en",
    {"es": {"speech_generation": {"voice_id": "default_high"}}, "fr": {}},
    input_sample_rate=48000,
)
task["pipeline"]["transcription"]["silence_threshold"] = 0.75

async with Palabra().translation(task=task) as session:
    ...

The client does not validate settings — invalid options are rejected by the server (TaskError is raised on async with, with the server's reason). The full list of options, their constraints, and tuning advice live in the docs: see Recommended Settings.

Offline files (utility)

For testing and batch jobs there are file helpers — but keep in mind this is a real-time service: the input is paced to real time, so translating a file takes roughly as long as the audio itself. For UX experiments and pipeline debugging it's convenient; for bulk offline processing it's the wrong tool.

palabra.translate_file(
    "speech_en.wav",
    source="en",
    targets="es",
    output="speech_es.wav",
    on_transcript=print
)
# mp3/ogg/resampling need: uv add "palabra-ai[audio]"

Related helpers: session.send_file(path), session.send_pcm(pcm) (chunking + real-time pacing built in), load_pcm / read_wav / write_wav.


Speech-to-Text API

Standalone transcription API (with optional translation). You push raw audio frames in and receive incremental transcriptions back; set translate_languages to also get a translation of each finalized segment.

All settings are sent as query parameters, audio goes out as raw binary frames.

Quick start

import asyncio
from palabra_ai import Palabra, SttTranscript

async def main():
    palabra = Palabra()

    async with palabra.stt(language="en") as stt:

        async def feed():
            # any audio source: PCM s16le, 16 kHz, mono, ~320 ms per chunk, real-time paced
            while chunk := await audio_buffer.get():
                await stt.send_audio(chunk)

        feeder = asyncio.create_task(feed())

        async for event in stt:
            if isinstance(event, SttTranscript):
                print(event) # "~ [en] partial" / "[en] final"

        await feeder

asyncio.run(main())

Iteration ends when the server closes the connection (or raises SessionError if the receive loop crashed).

Events

Iterating the session yields SttTranscript events (anything unrecognized comes through as Raw):

Field Meaning
text segment.text — the full segment text so far
language source language of the segment; the target language on a translation
transcription_id stable per segment; shared by all messages (incl. the translation) of one segment
is_eos False while the segment is still being updated; True once committed/final
is_translation True for translated_transcription (emitted once per target after each final segment)
start_time / end_time segment timing in seconds from session start
delta text appended since the previous transcript

With the filler filter enabled the segment tail may be rewritten midsegment, so render text whole on each message rather than appending delta.

Settings

All settings are keyword arguments of stt(...) and become URL query parameters:

async with Palabra().stt(
    language="en",                       # source; defaults to auto-detect
    format="pcm_s16le",                  # see the audio-formats table in the docs
    sample_rate=16000,                   # required for raw PCM other than 16 kHz pcm_s16le
    translate_languages=["es", "de"],    # also emit translated_transcription per target
    enable_filler_filter=True,           # server default: True for every language but ja
) as stt:
    ...

Realtime TTS API

Standalone synthesis, no translation pipeline. Designed for incremental text (LLM token streams): send pieces as they come, audio chunks come back with minimal latency.

Two methods. send_text() -- incremental streaming, e.g. straight from an LLM token stream; mark the end of each sentence with eos=True and consume TtsChunk events as they arrive:

async with palabra.tts(language="en", voice_id="default_low") as tts:
    await tts.send_text("The sun was setting over the mountains,")
    await tts.send_text(" casting long golden shadows.", eos=True)

    async for chunk in tts: # TtsChunk: audio, generation_id, last_chunk, audio_len
        play(chunk.audio)
        if chunk.last_chunk:
            break

    await tts.cancel() # stop current synthesis, session stays open

Each send_text() message is limited to 256 characters (the server limit); longer text raises ValueError -- splitting is up to you.

synthesize() -- one sentence in, audio bytes out:

async with palabra.tts(language="en", voice_id="default_low") as tts:
    pcm = await tts.synthesize("Curious minds think alike.")   # bytes (pcm s16le by default)

Options & limits

All palabra.tts(...) options (languages, voices, speed, output formats, sample rates), rate limits, and constraints are described in the Realtime TTS API docs. Per-message voice overrides can be passed as keyword arguments of send_text()/synthesize().

TTS is currently available in the eu and us regions.


Common reference

Errors

Shared by all APIs:

  • AuthError — missing/invalid API Key.
  • SessionError — WebSocket connection problems (including a crashed receive loop — the original exception is attached as __cause__).
  • NotReadyError — the pipeline didn't confirm set_task in time (translation only).
  • TaskError — the server rejected set_task (raised immediately on async with, with the server's code/desc), or raised by session.raise_on_error(event) for server error messages; by default in-stream errors are delivered as ServerError events so a long-running stream survives recoverable errors.
  • ValueError — the requested product is not available in the configured region, or an unknown region was set.

Reconnection

There is no automatic WebSocket reconnect, by design: a session is tied to one connection and to server-side pipeline state, so a transparent resume would silently lose the audio in flight and the transcription context. When the connection drops, iteration simply ends (or SessionError is raised if the receive loop crashed).

If your application needs resilience, build the retry loop on top — you control what state to restore:

while True:
    try:
        async with palabra.translation(source="en", targets=["es"]) as session:
            ...  # feed audio, consume events
        break  # finished normally
    except (SessionError, NotReadyError):
        await asyncio.sleep(1)  # reconnect with your own backoff policy

Examples

File What it shows
examples/realtime_tts.py Realtime TTS API streaming-in generation example
examples/realtime_stt.py Realtime Speech-to-Text API example live microphone example (uv add "palabra-ai[devices]")
examples/sts_buffer_streaming.py Realtime Speech-to-Speech API feeding chunks + async event loop
examples/sts_mic_to_speakers.py Realtime Speech-to-Speech API live microphone translation (uv add "palabra-ai[devices]")
examples/sts_multi_language.py Realtime Speech-to-Speech API several targets, per-target voices
examples/sts_file_to_file.py Realtime Speech-to-Speech API offline file translation (see the caveat above)

Development

uv sync --dev   # editable install + pytest/ruff
make check      # ruff check + tests + format check

Migrating from 1.x

1.x 2.0
Palabra(client_id=..., client_secret=...) / PALABRA_CLIENT_ID, PALABRA_CLIENT_SECRET Palabra(api_key=..., region=...) / PALABRA_API_KEY, PALABRA_REGION — create the key at platform.palabra.dev/api-keys
REST session management: create_session() / delete_session() / session= / Session removed — the API Key authorizes the WebSocket directly, sessions are managed server-side
Palabra(api_url=...) removed — endpoints are derived from region (see Regions)
ws_url= + token= direct mode removed

Migrating from 0.x

0.x (<= 0.6.x) 1.0
PalabraAI() + Config(SourceLang(EN, reader), [TargetLang(ES, writer)]) + palabra.run(cfg) Palabra().translation(source="en", targets="es") + send_audio / events
FileReader / FileWriter / BufferReader / adapters plain bytes: feed any source via send_audio; file utilities for tests
DeviceManager use sounddevice directly (see mic_to_speakers.py)
on_transcription= callbacks async for event in session
WebRTC transport not included; see the WebRTC note above

Download files

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

Source Distribution

palabra_ai-2.0.0.tar.gz (65.8 kB view details)

Uploaded Source

Built Distribution

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

palabra_ai-2.0.0-py3-none-any.whl (24.1 kB view details)

Uploaded Python 3

File details

Details for the file palabra_ai-2.0.0.tar.gz.

File metadata

  • Download URL: palabra_ai-2.0.0.tar.gz
  • Upload date:
  • Size: 65.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for palabra_ai-2.0.0.tar.gz
Algorithm Hash digest
SHA256 4b2b964f4fa551ae1e6a882601e6e6032b0b0fe26f7791b60e7232617d6462d7
MD5 552eeb23d4955a91d45d178893cf6fb8
BLAKE2b-256 6e00f30025d54f985efdf34fbc13512303501a9decb1a96286182f5eceb4c2d5

See more details on using hashes here.

File details

Details for the file palabra_ai-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: palabra_ai-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 24.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for palabra_ai-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b785a2ff67977975f590e7ec86b6e3ae6db6b3e79df87c841dbec1396902f992
MD5 ed6e916f95cd989105215f21ec371f3a
BLAKE2b-256 23e69eb148f0cd86e97906677321800418d4b3043c07b88a6814651303bdde67

See more details on using hashes here.

Release history Release notifications | RSS feed

2.1.1

2 files

2.1.0

2 files

2.0.2

2 files

2.0.1

2 files

This release

2.0.0 This release

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

0.6.11

2 files

0.6.10

2 files

0.6.9

2 files

0.6.8

2 files

0.6.7

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.12

2 files

0.5.11

2 files

0.5.10

2 files

0.5.9

2 files

0.5.8

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.3

2 files

0.1.2

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page