Sections
MeetWave API · Streaming
Streaming protocol
Every message of the streaming WebSocket: config, audio frames and stop; ready, partial, final, ack, warning and stopped; how to reconnect, the close codes and the limits.
Connect
Open wss://stream.meetwave.io/v1/stream: a standard WebSocket over TLS. Authenticate the opening request one of two ways:
| Credential | Form | Meaning |
|---|---|---|
Authorization | Bearer mwk_… | Your API key, on the opening request. From a server only. |
token | query string | From a browser: a token from POST /v1/stream/tokens. It opens one connection within 1 minute. |
Name the language in the address to get the first text sooner: wss://stream.meetwave.io/v1/stream/ru. It is optional; without it the config’s language decides. When both are given they must match, or the connection closes with 4002.
Messages are not compressed: a client that offers compression gets a connection without it. Audio itself keeps the connection open. A client that can send WebSocket pings may send one every 20 to 30 seconds; a browser or Node’s built-in WebSocket cannot, and does not need to.
Send: config, audio, stop
The first message is the config, as JSON text:
{
"type": "config",
"tier": "text",
"language": "en",
"encoding": "pcm_s16le",
"sample_rate": 16000
}| Field | Value | Meaning |
|---|---|---|
type | "config" | The first message, within 10 seconds of opening. |
tier | text | speakers | names | What the transcript holds at stop, and the price. |
language | en | a code | auto | Live text in en, es, pt, ru, de, fr, it (de, fr, it as a preview). Any other language the Files API accepts, or auto, gets its text at stop. |
encoding | "pcm_s16le" | The only encoding: signed 16-bit, little-endian. |
sample_rate | 16000 | The only rate. Audio is mono. |
resume | {session_id, from_s, last_final_end} | Only when reconnecting: the session, the audio second you resend from and, optionally, the end of the last final you showed. |
After ready, send audio as binary messages: 16 kHz mono, signed 16-bit little-endian PCM, 20 ms to 1 s per message (640 to 32000 bytes, an even number). Audio recorded before ready may be sent all at once then.
When there is no more audio, send:
{"type": "stop"}The server finishes the last phrase, answers stopped and closes with 1000. Fetch the transcript with GET /v1/transcriptions/{id} using the transcript_id, or wait for its webhook.
Receive
The server sends JSON text messages, each with a type. Times are seconds from the start of the session’s audio and run on across reconnects.
| Type | Fields | Meaning |
|---|---|---|
ready | session_id, transcript_id, live | Send audio now. live is false when the language has no live text. On a resume it adds resumed_from_s. |
partial | text, start, end | The phrase so far. The next partial of the same phrase replaces it. |
final | text, start, end, words | A finished phrase, after 0.8 s of silence. words holds each word with its times. |
ack | audio_s | Audio up to here is stored: drop it from what you would resend. At least every 30 seconds. |
warning | code, seconds_left | code low_balance: your credits cover about seconds_left more seconds. Top up to keep going. |
stopped | transcript_id, status, audio_s | The answer to stop. status is completed, or processing while the transcript is built. |
error | code, message | Sent right before the server closes with a 4xxx code. |
A final:
{
"type": "final",
"text": "Budget first.",
"start": 12.4,
"end": 13.3,
"words": [
{
"w": "Budget",
"start": 12.4,
"end": 12.9
},
{
"w": "first.",
"start": 12.9,
"end": 13.3
}
]
}Reconnect without losing words
Keep the audio you sent after the last ack. When the connection drops with a code marked “reconnect” below, open a new one within 2 minutes and send the config with resume: the session_id and, as from_s, the last ack’s audio_s. Then resend the kept audio from there. Resent audio is not charged twice. Add last_final_end, the end of the last final you showed, and text before it is not sent again; without it, skip what you already showed yourself.
Close codes
| Code | Meaning |
|---|---|
1000 | Normal: after stopped, or the client closed. |
1001 | Going away. Reconnect and resume. |
1006 | The connection dropped. Reconnect and resume. |
1011 | internal_error Internal error. Reconnect and resume. |
1012 | Service restart. Reconnect and resume. |
1013 | try_again Try again later: busy, or billing briefly unreachable. Reconnect and resume. |
4001 | unauthorized Bad, inactive or expired key or token. |
4002 | invalid_message Bad config (for example a language the Files API does not accept), bad frame, or audio too far ahead of real time. |
4003 | forbidden Not connected through the MeetWave stream address. |
4008 | idle No audio for 60 seconds. |
4013 | session_limit The session reached 4 hours of audio. |
4029 | too_many_sessions More than 10 sessions at once for this account. |
4402 | insufficient_credits Not enough credits for the next 5 minutes; the current phrase is finished first. |
4404 | session_not_found Session not found, or its 2-minute resume window passed. |
4409 | session_in_use A newer connection resumed this session; this one is closed. |
Limits
| Limit | Value |
|---|---|
| From opening to the config message | 10 seconds |
| Silence before the server closes (4008) | 1 minute |
| Audio ahead of real time, to resend a backlog | 2 minutes |
| Audio in one session, across reconnects | 4 hours |
| Sessions at once per account | 10 |
| Time to reconnect to a dropped session | 2 minutes |
Billing is per second of audio received, at the tier’s price. When your credits run low the server sends warning; when they cannot cover the next 5 minutes, it finishes the current phrase within 15 seconds and closes with 4402.
