pipecat-saidwire
Saidwire real-time speech-to-text for Pipecat.
SaidwireSTTService streams your user's audio to Saidwire over a WebSocket and pushes
InterimTranscriptionFrames while they speak and a TranscriptionFrame when they finish.
When your VAD decides the user stopped talking, the service sends Finalize, and the
final transcript comes straight back, so turn-taking doesn't wait on a server-side pause.
Saidwire is English-only. Pricing is $0.30 per audio hour, billed per second of audio sent. Get a key at saidwire.com/dev.
This package is built and maintained by Saidwire, the company that runs the service.
Tested with Pipecat v1.15.0 (Python 3.11+).
Installation
uv add pipecat-saidwire
# or
pip install pipecat-saidwire
Set your key:
export SAIDWIRE_API_KEY=your_key
Usage with a Pipecat pipeline
from pipecat.pipeline.pipeline import Pipeline
from pipecat_saidwire import SaidwireSTTService
stt = SaidwireSTTService() # reads SAIDWIRE_API_KEY
pipeline = Pipeline(
[
transport.input(),
stt,
user_aggregator,
llm,
tts,
transport.output(),
assistant_aggregator,
]
)
Already have a Pipecat bot? Replace your current STT service with the stt = ... line.
Nothing else changes.
Running the example
examples/bot.py is a complete voice agent (Saidwire STT, an OpenAI
LLM, Cartesia TTS, Silero VAD) that you talk to from your browser:
pip install "pipecat-ai[webrtc,daily,silero,openai,cartesia,runner]" pipecat-saidwire
export SAIDWIRE_API_KEY=... OPENAI_API_KEY=... CARTESIA_API_KEY=...
python examples/bot.py
# open http://localhost:7860/client and start talking
examples/transcribe_file.py streams a WAV file through a
pipeline in real time and prints the transcripts. It needs only a Saidwire key:
python examples/transcribe_file.py call.wav
How it behaves in a pipeline
| Pipecat | Saidwire |
|---|---|
InputAudioRawFrame |
streamed as 16-bit PCM at the pipeline's input rate (8-48 kHz) |
InterimTranscriptionFrame |
interim results while the user is speaking |
TranscriptionFrame |
final result for an utterance; its words won't change |
VADUserStoppedSpeakingFrame |
sends Finalize; the final comes back right away, marked finalized=True |
EndFrame |
sends CloseStream, then closes |
STTUpdateSettingsFrame |
applied by reconnecting between user turns |
| muted or idle | a KeepAlive message holds the stream open (silence would be billed as audio) |
Dropped connections reconnect with backoff. A bad or revoked key, or used-up credit, is
reported once as a permanent error, with no retry loop. If the service answers "starting
up" or "busy" (HTTP 503 or 429), the service waits for the Retry-After time and tries
again, for up to warmup_timeout seconds (default 300). Audio sent while it waits is not
transcribed.
Configuration
stt = SaidwireSTTService(
api_key="...", # default: $SAIDWIRE_API_KEY
sample_rate=None, # default: the pipeline's input rate
settings=SaidwireSTTService.Settings(
endpointing=None, # server default; False = finals only from Finalize / long pauses
interim_results=True,
punctuate=True,
early_words=False, # True: on_early_word for each word as soon as it is committed
vad_events=False, # True: on_speech_started when the server hears speech begin
utterance_end_ms=None, # e.g. 1000: on_utterance_end after 1 s of silence
),
vad_force_finalize=True, # VADUserStoppedSpeakingFrame -> Finalize (recommended)
warmup_timeout=300.0,
)
Constructor parameters:
| parameter | default | meaning |
|---|---|---|
api_key |
$SAIDWIRE_API_KEY |
your Saidwire API key |
base_url |
wss://api.saidwire.com/v1/listen |
streaming endpoint |
sample_rate |
pipeline input rate | 8000-48000 |
vad_force_finalize |
True |
send Finalize when the VAD says the user stopped |
warmup_timeout |
300.0 |
seconds to keep retrying while the service is starting up |
ttfs_p99_latency |
0.30 |
hint for Pipecat turn strategies; measure your own deployment |
Runtime Settings (change them with STTUpdateSettingsFrame):
| setting | default | meaning |
|---|---|---|
model |
saidwire-en-2026-10-30 |
model id |
language |
en |
en, en-US, en-GB, ... (English only) |
endpointing |
None |
ms of pause that ends an utterance on the server; False to leave turn-taking to your VAD; None for the server default |
interim_results |
True |
interim transcripts while the user speaks |
punctuate |
True |
punctuation and capitals |
early_words |
False |
on_early_word events |
vad_events |
False |
on_speech_started events |
utterance_end_ms |
None |
on_utterance_end events after this much silence |
Events
@stt.event_handler("on_early_word")
async def on_early_word(stt, word):
# {"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.
...
@stt.event_handler("on_speech_started") # vad_events=True
async def on_speech_started(stt, message): ...
@stt.event_handler("on_utterance_end") # utterance_end_ms set
async def on_utterance_end(stt, message): ...
Plus the standard on_connected, on_disconnected and on_connection_error.
stt.request_id is the id of the current stream; include it when you contact support.
Protocol
Saidwire's streaming API uses the Deepgram-compatible /v1/listen protocol, so you can
also point an existing /v1/listen client at wss://api.saidwire.com with your Saidwire
key. This package adds Saidwire defaults and the extras above. API reference:
saidwire.com/docs/api.
Development
uv sync --group dev # or: pip install -e . pytest pytest-asyncio ruff
pytest # runs against a fake server on 127.0.0.1; no key, no network
ruff check . && ruff format --check .
Support
Open an issue on this repository, or email support@saidwire.com.
License
MIT. See LICENSE.
Metadata
Release files for pipecat-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 |
|---|---|---|---|---|
| pipecat_saidwire-0.1.0.tar.gz | 20.8 kB | Without provenance | Details for pipecat_saidwire-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pipecat_saidwire-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for pipecat_saidwire-0.1.0-py3-none-any.whl |
Total release size: 32.5 kB
Release files / pipecat_saidwire-0.1.0.tar.gz
| Download URL | pipecat_saidwire-0.1.0.tar.gz |
|---|---|
| Size | 20.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0da4bfc4aa537e7d9ab373a85c46c2d7f1f8a55615e0b0318a63f5a43eec3696
|
|
BLAKE2b-256 checksum How to use checksums |
640735da5e01bbf21d62b974a7d9175bced928ee4da6e15b3b49a95314324910
|
| 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 / pipecat_saidwire-0.1.0-py3-none-any.whl
| Download URL | pipecat_saidwire-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c67ab36528238033770cca317310f3b2d1d42cbd4367a4df8598f7baa61d8d3d
|
|
BLAKE2b-256 checksum How to use checksums |
5b78654a3b5d9f7820e55c1843150c801c424aa45d26aa90c4cd84ed63d8df52
|
| 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 pipecat-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.