Overview
WaveSTTService provides streaming speech-to-text through
.wave, over its /v1/listen WebSocket, a
Deepgram-compatible streaming transcription endpoint. The service extends
Pipecat’s WebsocketSTTService and pushes InterimTranscriptionFrame and
TranscriptionFrame results into the pipeline. When the VAD reports the end of
speech, it sends Finalize and marks the answering transcription as finalized.
Source Repository
Source code, README, and issues for the .wave integration
Example
Transcribe a browser microphone in a single file
.wave Socket Reference
Messages, parameters, languages, and close codes
.wave
Create an account and an API key
PyPI Package
The
pipecat-dotwave package on PyPIInstallation
This is a community-maintained package distributed separately frompipecat-ai:
Prerequisites
.wave Account Setup
Before using the .wave STT service, you need:- .wave Account: Sign up at dotwave.ai
- API Key: Create an API key in the .wave console
Required Environment Variables
DOTWAVE_API_KEY: Your .wave API key for authentication
Configuration
str
required
.wave API key, sent as
Authorization: Token <key>.str
default:"api.dotwave.ai"
API endpoint: a bare host, or a URL with a scheme such as
ws://localhost:8080. A bare host uses wss.str
default:"linear16"
Encoding sent on the socket:
"linear16", "mulaw", or "alaw". Pipeline
audio is converted as needed: linear16 is sent at 16 or 24 kHz (other rates
are resampled to 16 kHz), mulaw and alaw at 8 kHz.int
default:"None"
Sample rate of the incoming audio in Hz. If
None, uses the pipeline’s input
sample rate.int
default:"None"
Silence in milliseconds (1000 to 3200) after which the socket ends a segment
on its own, sending a final with
speech_final and an UtteranceEnd message.
If None, segments end on Finalize, which the service sends when the VAD
reports the end of speech.bool
default:"True"
Whether to receive interim results.
dict[str, str]
default:"None"
Additional headers for the WebSocket handshake. Merged after the default
headers, so they can override them.
bool
default:"True"
Push one
TranscriptionFrame per segment, holding the whole segment, with
InterimTranscriptionFrames carrying the segment so far. False pushes one
frame per socket result instead, often one word at a time. See “How results
arrive” under Notes.float
default:"None"
P99 latency from speech end to final transcript, in seconds, used by turn
strategies. .wave has not measured this value for Pipecat, so Pipecat’s
default applies if
None. Measure your deployment with
stt-benchmark and pass the
result.Settings
Runtime-configurable settings passed via thesettings constructor argument
using WaveSTTService.Settings(...). These can be updated mid-conversation with
STTUpdateSettingsFrame; a change reconnects the socket.
Usage
Basic Setup
With a Language and a Segment Rule
Telephony Audio
Notes
- VAD required for timely finals: Put a VAD upstream of the service (a
VADProcessor, or the user aggregator’s VAD). OnVADUserStoppedSpeakingFramethe service sendsFinalize, and the transcription that answers it is pushed withfinalized=True. - How results arrive: The socket sends a final as soon as words are
settled, often one word at a time. By default the service collects them and
pushes one
TranscriptionFrameper segment. A segment ends when the socket answersFinalize(the frame is markedfinalized), when a final is markedspeech_finalor anUtteranceEndarrives (withutterance_end_ms), or when the service stops or reconnects with words pending. While a segment is open, each interim and each final pushes anInterimTranscriptionFramewith the segment so far, so turn strategies and RTVI clients show live text. Finals join with one space, except in Chinese and Japanese where they join with no separator. Withsegment_finals=False, each socket result is its own frame. - Languages: A Pipecat
Languageis sent as the tag the socket expects. Regional values pass through (Language.PT_BRaspt-BR),Language.ENis sent asen(English, United States), and a bare code with a single regional variant is sent as that variant (Language.DEasde-DE). You can also pass a tag string such as"pt-BR". A language .wave does not serve is refused when the socket opens, with an error naming the tags it does serve. Frames carry the reported language as a PipecatLanguage, and none with automatic detection. - Not supported:
diarize,multichannel,channels,keywords, andendpointing. Passing them to the constructor raisesTypeError. - Keepalive: A session closes after 30 seconds without audio, so the service sends a short burst of silence after 20 idle seconds.
- Errors:
Errormessages from the socket are pushed asErrorFrame. A refused API key (close code 4401) or a malformed request (4400) is permanent and not retried; other closes reconnect with backoff. - Pricing: $0.00045 per minute of audio. See pricing and limits.
Event Handlers
WaveSTTService supports the standard service connection events: