Skip to main content

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 PyPI

Installation

This is a community-maintained package distributed separately from pipecat-ai:

Prerequisites

.wave Account Setup

Before using the .wave STT service, you need:
  1. .wave Account: Sign up at dotwave.ai
  2. 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.
WaveSTTService.Settings
default:"None"
Runtime-updatable settings. See Settings below.
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 the settings 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). On VADUserStoppedSpeakingFrame the service sends Finalize, and the transcription that answers it is pushed with finalized=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 TranscriptionFrame per segment. A segment ends when the socket answers Finalize (the frame is marked finalized), when a final is marked speech_final or an UtteranceEnd arrives (with utterance_end_ms), or when the service stops or reconnects with words pending. While a segment is open, each interim and each final pushes an InterimTranscriptionFrame with 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. With segment_finals=False, each socket result is its own frame.
  • Languages: A Pipecat Language is sent as the tag the socket expects. Regional values pass through (Language.PT_BR as pt-BR), Language.EN is sent as en (English, United States), and a bare code with a single regional variant is sent as that variant (Language.DE as de-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 Pipecat Language, and none with automatic detection.
  • Not supported: diarize, multichannel, channels, keywords, and endpointing. Passing them to the constructor raises TypeError.
  • Keepalive: A session closes after 30 seconds without audio, so the service sends a short burst of silence after 20 idle seconds.
  • Errors: Error messages from the socket are pushed as ErrorFrame. 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:

Compatibility

Tested with Pipecat v1.12.0 and pipecat-dotwave 0.1.1. Requires Pipecat 1.12.0 or later and Python 3.11 or later. Check the source repository for the latest tested version and changelog.