Skip to main content

Saidwire plugin for LiveKit Agents

Support for Saidwire real-time speech-to-text in LiveKit Agents.

The plugin streams the user's audio to Saidwire over a WebSocket and emits interim and final transcripts. When the agent session's VAD or turn detector ends the user's turn, it flushes the stream; the plugin sends Finalize, and the final transcript comes straight back.

Saidwire is English-only. Pricing is $0.30 per audio hour, billed per second of audio sent. This plugin is built and maintained by Saidwire, the company that runs the service.

Tested with livekit-agents 1.8.10.

Installation

pip install livekit-plugins-saidwire

Pre-requisites

You'll need an API key from Saidwire (saidwire.com/dev). It can be set as an environment variable: SAIDWIRE_API_KEY.

Usage

from livekit.agents import AgentSession
from livekit.plugins import saidwire, silero

session = AgentSession(
    stt=saidwire.STT(),  # reads SAIDWIRE_API_KEY
    vad=silero.VAD.load(),
    llm=...,
    tts=...,
)

Already have an agent? Replace your current stt= with saidwire.STT(). Nothing else changes.

A complete agent is in examples/agent.py (its LLM and TTS go through LiveKit Inference, so only LiveKit credentials are needed for them):

pip install "livekit-agents[silero]" livekit-plugins-saidwire python-dotenv
export SAIDWIRE_API_KEY=...
export LIVEKIT_URL=... LIVEKIT_API_KEY=... LIVEKIT_API_SECRET=...
python examples/agent.py console      # talk to it in your terminal

Options

stt = saidwire.STT(
    api_key="...",  # default: $SAIDWIRE_API_KEY
    model="saidwire-en-2026-10-30",
    language="en",  # en, en-US, en-GB, ... (English only)
    sample_rate=16000,  # 8000 for telephony audio
    interim_results=True,
    punctuate=True,
    endpointing_ms=None,  # server default; 0 = leave turn-taking to the session
    utterance_end_ms=None,  # e.g. 1000: END_OF_SPEECH after 1 s of silence
    vad_events=False,  # True: START_OF_SPEECH from the server
    early_words=False,  # True: "early_word" events (below)
    warmup_timeout=300.0,  # seconds to wait while the service starts up
)
option meaning
endpointing_ms pause, in ms, that ends an utterance on the server. None uses the server default. 0 turns server endpointing off: finals come when the session flushes and at longer pauses.
utterance_end_ms the server sends UtteranceEnd (mapped to END_OF_SPEECH) after this much silence
vad_events the server sends SpeechStarted (mapped to START_OF_SPEECH)
early_words emit an early_word event for each word as soon as it is committed
warmup_timeout if the service answers "starting up" or "busy" (HTTP 503 / 429), wait for Retry-After and try again, for up to this many seconds. Audio pushed while waiting is not transcribed.

stt.update_options(...) changes options at runtime; open streams reconnect with them. recognize() sends pre-recorded audio to POST /v1/listen.

Early words

stt = saidwire.STT(early_words=True)


@stt.on("early_word")
def on_early_word(word: dict) -> None:
    # {"word": "cancel", "punctuated_word": "cancel.", "start": 6.84, "end": 7.29, ...}
    # Sent as soon as the word is committed, usually before the final that contains it.
    # Useful for keyword triggers ("stop", "cancel"). The final transcript is authoritative.
    ...

Behavior

  • The session's flush at end of turn sends Finalize; the answer is a final transcript (empty if everything was already final), so the session never waits on a timeout.
  • While audio is not flowing, a KeepAlive message holds the stream open. Silence would be billed as audio; KeepAlive is free.
  • Dropped connections are retried per APIConnectOptions. A bad or revoked key, or used-up credit, fails at once with a non-retryable APIStatusError.
  • stream.request_id is the id of the current connection; include it when you contact support.

Protocol

Saidwire's streaming API uses the Deepgram-compatible /v1/listen protocol. API reference: saidwire.com/docs/api.

Development

pip install -e . pytest pytest-asyncio ruff mypy numpy
pytest                     # runs against a fake server on 127.0.0.1; no key, no network
ruff check . && ruff format --check . && mypy livekit

Support

Open an issue on the source repository, or email support@saidwire.com.

Metadata

Release files for livekit-plugins-saidwire 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 livekit-plugins-saidwire 0.1.0
File Size Uploaded Provenance Actions
livekit_plugins_saidwire-0.1.0.tar.gz 15.0 kB Without provenance Details for livekit_plugins_saidwire-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for livekit-plugins-saidwire 0.1.0
File Interpreter ABI Platform Actions
livekit_plugins_saidwire-0.1.0-py3-none-any.whl Python 3 none any Details for livekit_plugins_saidwire-0.1.0-py3-none-any.whl

Total release size: 32.6 kB

Release files / livekit_plugins_saidwire-0.1.0.tar.gz

Download URL livekit_plugins_saidwire-0.1.0.tar.gz
Size 15.0 kB
Tags Source
SHA-256 checksum
How to use checksums
da46847323648b14971f5b81cae1b53deee2a25a13a4d96542508da380e6dafe
BLAKE2b-256 checksum
How to use checksums
be71f7a7f953154912973092cbe95d487137d7e51174305f38cb7cd05e0811df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","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}

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

Download URL livekit_plugins_saidwire-0.1.0-py3-none-any.whl
Size 17.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
32e0fc5bc22e7382b01509c06bbe68526758b3f5ab94f7db109a6d168dd4ecf9
BLAKE2b-256 checksum
How to use checksums
8cb2f7ed2cf3ca85b7246c28a3ec19f28d850982f68e6cda80b5a33b5429be5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","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}

Security for livekit-plugins-saidwire 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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