# Meta

> Realtime speech-to-text with MetaSTTService, over Meta's Muse Voice WebSocket API.

Source: https://polvallverdu.github.io/pipedog/docs/services/stt/meta/



## Overview [#overview]

* **`MetaSTTService`**: streams audio over a WebSocket to Meta's realtime transcription endpoint. Cumulative partials become `InterimTranscriptionFrame`s; the post-processed text of each segment becomes a `TranscriptionFrame`.

<Cards>
  <Card title="Upstream page" href="https://docs.pipecat.ai/api-reference/server/services/stt/meta">
    Pipecat's documentation for the same service.
  </Card>

  <Card title="Source" href="https://github.com/polvallverdu/pipedog/tree/main/packages/meta/src">
    `packages/meta/src/stt.ts`.
  </Card>

  <Card title="Meta docs" href="https://dev.meta.ai/docs/api-reference/voice/realtime">
    The realtime voice API reference.
  </Card>
</Cards>

## Installation [#installation]

```bash
bun add @pipedog/meta
```

```ts
import { MetaSTTService } from "@pipedog/meta/stt";
```

## Prerequisites [#prerequisites]

* A Meta Model API key from [Meta's developer site](https://dev.meta.ai/).
* Pass the key as `apiKey`. The examples read it from `META_API_KEY`.

## MetaSTTService [#metasttservice]

Connects to `wss://api.meta.ai/v1/asr/realtime`. The key travels in the handshake message as a Bearer token, not in an HTTP header, and the session's configuration is fixed once the server accepts it, so a settings change reconnects.

### Configuration [#configuration]

| Option | Type | Required | Description |
|---|---|---|---|
| `apiKey` | `string` | yes | Meta Model API key, sent as a Bearer token in the handshake. |
| `url` | `string \| undefined` | no | WebSocket endpoint URL. Defaults to `wss://api.meta.ai/v1/asr/realtime`. |
| `settings` | `MetaSTTSettings \| null \| undefined` | no | Runtime-updatable settings overriding defaults. |
| `name` | `string \| null \| undefined` | no | Custom name; defaults to `ClassName#count`. |
| `taskManager` | `BaseTaskManager \| null \| undefined` | no | Task manager for handling tasks. |
| `enableDirectMode` | `boolean \| undefined` | no | Process frames immediately instead of using internal queues. |
| `metrics` | `FrameProcessorMetrics \| null \| undefined` | no | Optional metrics collector for this processor. |
| `reconnectBackoffMinWait` | `number \| undefined` | no | Minimum time, in seconds, to wait between reconnection attempts. |
| `reconnectBackoffMaxWait` | `number \| undefined` | no | Maximum time, in seconds, to wait between reconnection attempts. |
| `wsCloseTimeout` | `number \| undefined` | no | Maximum time, in seconds, to wait for the peer to acknowledge the websocket closing handshake before dropping the connection. Applied to connections opened through `_websocketConnect()`. Increase it for peers that need longer to complete a graceful close. |
| `wsSendTimeout` | `number \| null \| undefined` | no | Maximum time, in seconds, a single send may wait on a peer that has stopped reading before the connection is dropped and the send throws `ConnectionClosedError`. Applied to connections opened through `_websocketConnect()`. Pass `null` to wait indefinitely. Defaults to `WS_SEND_TIMEOUT`. |
| `audioPassthrough` | `boolean \| undefined` | no | Whether to pass audio frames downstream after processing. Defaults to true. |
| `sampleRate` | `number \| null \| undefined` | no | The sample rate for audio input. If null, will be determined from the start frame. |
| `sttTtfbTimeout` | `number \| undefined` | no | Time in seconds to wait after VAD stop before reporting TTFB. This delay allows the final transcription to arrive. Defaults to 2.0. |
| `ttfsP99Latency` | `number \| null \| undefined` | no | P99 latency from speech end to final transcript in seconds. Broadcast via STTMetadataFrame at pipeline start. |
| `keepaliveTimeout` | `number \| null \| undefined` | no | Seconds of no audio before sending silence to keep the connection alive. null disables keepalive. |
| `keepaliveInterval` | `number \| undefined` | no | Seconds between idle checks when keepalive is enabled. |
| `reconnectOnError` | `boolean \| undefined` | no | Whether to automatically reconnect on websocket errors. Defaults to true. |

### Settings [#settings]

Runtime-updatable settings, passed as `settings: new MetaSTTService.Settings({...})`
(`MetaSTTSettings`). Any setting you leave out keeps the default below.

| Setting             | Type                 | Default                       | Description                                                                                               |
| ------------------- | -------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------- |
| `model`             | `string`             | `"muse-voice-transcribe-1.0"` | Transcription model.                                                                                      |
| `language`          | `Language \| null`   | `Language.EN`                 | Language to bias recognition toward. Leave it and `languageBias` unset to auto-detect.                    |
| `languageBias`      | `Language[] \| null` | `null`                        | Languages to bias toward, for speech that switches between them. Replaces `language` when set.            |
| `mode`              | `string`             | `"ENDPOINTING"`               | `"ENDPOINTING"` (the model marks turn boundaries), `"PUSH_TO_TALK"` or `"DIARIZATION"`.                   |
| `keywords`          | `string[] \| null`   | `null`                        | Terms to bias recognition toward. Biasing doesn't guarantee a spelling.                                   |
| `emitAudioProgress` | `boolean`            | `false`                       | Have the server report progress for every processed audio chunk.                                          |
| `zdrOverride`       | `boolean \| null`    | `null`                        | `true` forces metadata-only logging; `false` allows content retention; `null` uses the account's setting. |

### Usage [#usage]

```ts title="stt.ts"
import { Language } from "@pipedog/core/transcriptions/language";
import { MetaSTTService } from "@pipedog/meta/stt";

const stt = new MetaSTTService({
  apiKey: process.env.META_API_KEY ?? "",
  settings: new MetaSTTService.Settings({ language: Language.EN, keywords: ["pipedog"] }),
});
```

### Event handlers [#event-handlers]

| Event             | Description              |
| ----------------- | ------------------------ |
| `on_connected`    | The WebSocket connected. |
| `on_disconnected` | The WebSocket closed.    |

### Notes [#notes]

* Audio is sent at 24000 Hz, or 16000 Hz for any other pipeline rate (resampled), the only two rates the API accepts.
* The server's turn boundaries only segment transcripts. The VAD and turn strategies still decide when the user's turn ends.
* Sessions are capped at 60 minutes. The server then closes the socket, and the service reconnects into a fresh one.

| 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/meta/package.json`: ✅ means the compat smoke test passes on that runtime.

## Runtime notes [#runtime-notes]

* The WebSocket goes through the core `websocketConnect`. It works on Bun, Node, Deno and Cloudflare Workers.
* Tested against local WebSocket servers, as upstream's tests do, not against Meta itself.
