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
KeepAlivemessage holds the stream open. Silence would be billed as audio;KeepAliveis free. - Dropped connections are retried per
APIConnectOptions. A bad or revoked key, or used-up credit, fails at once with a non-retryableAPIStatusError. stream.request_idis 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.