Smallest AI
Realtime speech-to-text with SmallestSTTService, over Smallest AI's Pulse WebSocket API.
Overview
SmallestSTTService: streams audio over a persistent WebSocket to Smallest AI's Pulse speech-to-text endpoint. Interim transcripts becomeInterimTranscriptionFrames; when the VAD sees the user stop, the service sendsfinalizeand the final becomes aTranscriptionFrame.
Upstream page
Pipecat's documentation for the same service.
Source
packages/smallest/src/stt.ts.
Smallest AI docs
The realtime WebSocket reference.
Installation
bun add @pipedog/smallestimport { SmallestSTTService } from "@pipedog/smallest/stt";Prerequisites
- A Smallest AI account and an API key from Smallest AI.
- Pass the key as
apiKey. The examples read it fromSMALLEST_API_KEY.
SmallestSTTService
Connects to wss://api.smallest.ai/waves/v1/stt/live, with the key as a Bearer token on the handshake.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new SmallestSTTService.Settings({...})
(SmallestSTTSettings). Any setting you leave out keeps the default below.
| Setting | Type | Default | Description |
|---|---|---|---|
model | "pulse" | "pulse-2" | "pulse" | pulse-2 is English-only and adds per-utterance emotion and gender. |
language | Language | Language.EN | Language of the audio. A non-English language with pulse-2 throws. |
wordTimestamps | boolean | false | Word-level timestamps. |
fullTranscript | boolean | false | Include the cumulative transcript. |
sentenceTimestamps | boolean | false | Sentence-level timestamps. |
redactPii | boolean | false | Redact personally identifiable information. |
redactPci | boolean | false | Redact payment card information. |
numerals | string | "auto" | Convert spoken numerals to digits. |
diarize | boolean | false | Speaker diarization. |
endpointing | boolean | true | Finalize promptly on trailing silence. No effect on pulse-2. |
keywords | string | "" | Comma-separated KEYWORD:INTENSIFIER pairs, such as "NVIDIA:2". |
format | boolean | true | Punctuation and capitalization. |
emotionDetection | boolean | true | pulse-2 only: a six-class emotion on each final. |
genderDetection | boolean | true | pulse-2 only: a gender estimate on each final. |
itnNormalize | boolean | false | Inverse text normalization ("twenty five" becomes "25"). |
noFormatDelay | boolean | false | With itnNormalize, emit finals at once instead of holding back a number still being dictated. |
Usage
import { Language } from "@pipedog/core/transcriptions/language";
import { SmallestSTTService } from "@pipedog/smallest/stt";
const stt = new SmallestSTTService({
apiKey: process.env.SMALLEST_API_KEY ?? "",
settings: new SmallestSTTService.Settings({ language: Language.EN, wordTimestamps: true }),
});Pulse 2.0, English only:
const pulse2 = new SmallestSTTService({
apiKey: process.env.SMALLEST_API_KEY ?? "",
settings: new SmallestSTTService.Settings({ model: "pulse-2" }),
});
Change settings mid-call with an STTUpdateSettingsFrame:
import { STTUpdateSettingsFrame } from "@pipedog/core/frames/frames";
// Queue it on the worker, or push it from a processor upstream of the service.
const update = new STTUpdateSettingsFrame({
delta: new SmallestSTTService.Settings({ redactPii: true }),
});Event handlers
| Event | Description |
|---|---|
on_connected | The WebSocket connected. |
on_disconnected | The WebSocket closed. |
Notes
encodingis"linear16"by default.sampleRatedefaults to the pipeline's input rate.- Settings are query parameters of the connection, so changing one reconnects.
- The same package has Smallest AI's LLM and text-to-speech services.
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/smallest/package.json: ✅ means the compat smoke test passes on that runtime.
Runtime notes
- The WebSocket goes through the core
websocketConnect, with headers on the handshake. - Upstream sets a keepalive interval without implementing the keepalive message, so an idle connection logs a warning every few seconds. The port behaves the same way.
- Tested against local WebSocket servers, as upstream's tests do, not against Smallest AI itself.
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).