Desktop Speech Recognition WebSocket
Stream audio for real-time recognition while preserving the Desktop session, transcript, recording, diarization, and summary lifecycle.
Internal API
The Desktop API is internal and must not be used for customer integrations. Compatibility is not guaranteed, and these endpoints may change without notice.
Endpoint: /api/v1/desktop-services/speech-recognition
WebSocket subprotocol: koldan.desktop.v1
Requires Authentication - Scopes: desktop:app:use
Concurrency Limited - The installation can limit simultaneous Desktop recognition sessions.
Connect
Open a secure WebSocket connection and offer koldan.desktop.v1 in the Sec-WebSocket-Protocol header. The server rejects an upgrade that does not offer this subprotocol with 400 Bad Request.
const socket = new WebSocket(
"wss://koldan.dixilang.com/api/v1/desktop-services/speech-recognition",
"koldan.desktop.v1",
);
The access token is sent in the first WebSocket message, not in the connection URL.
Message sequence
Messages must follow this order:
- Open the connection with the
koldan.desktop.v1subprotocol. - Send one
authenticatetext message. - Send one binary
SpeechRecognitionRequestcontainingheader. - Send zero or more binary
SpeechRecognitionRequestmessages containingpacket. - Receive binary
SpeechRecognitionResponsemessages while recognition is active. - Send one
completetext message after the final audio packet. - Continue reading responses until the server sends
completed, then closes normally.
The server does not send a separate authentication acknowledgement. Ordered WebSocket delivery allows the client to send the header immediately after authenticate. The first SpeechRecognitionResponse.info confirms that recognition started and supplies the Desktop session identifier.
By default, the client must send authenticate within 30 seconds of opening the connection and the recognition header within 30 seconds of successful authentication. Either deadline closes the connection with an error message and WebSocket close code 1008. Installations can configure both deadlines.
Client text messages
authenticate
The first client message must authenticate the connection.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type |
string |
Yes | - | Must be authenticate. |
authentication |
Authentication |
Yes | - | Bearer-token authentication details. |
Authentication
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
token |
string |
Yes | - | OAuth2 JWT access token. Must be non-blank. |
tenantId |
string (UUID) |
No | Server default tenant | Tenant to use for this connection. |
{
"type": "authenticate",
"authentication": {
"token": "eyJhbGciOiJSUzI1NiIs...",
"tenantId": "c5a7d459-f313-4aa0-a978-182e7e3d2a3b"
}
}
complete
Signal that no more recognition requests will be sent. This half-closes client input; the connection remains open while the server finishes processing buffered audio.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type |
string |
Yes | - | Must be complete. |
Send complete only after authentication, the header, and all audio packets. Do not send another client message afterward.
Client binary messages
Every client binary message is one serialized Api.SpeechRecognitionRequest protobuf message. Do not add a length prefix, envelope, JSON encoding, or base64 encoding.
The first binary message must contain header. Every later binary message must contain packet.
SpeechRecognitionRequest
| Field | Protobuf field | Type | Default | Description |
|---|---|---|---|---|
header |
1 |
SpeechRecognitionHeader |
Unset | Header variant of the step oneof. Required in the first binary message. |
packet |
2 |
SpeechRecognitionPacket |
Unset | Audio-packet variant of the step oneof. Required in every later binary message. |
Exactly one step variant can be set. A request with no variant is invalid for this protocol.
SpeechRecognitionHeader
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
presetName |
1 |
string |
Required | - | Stable name of a preset assigned to the authenticated user. Use Assigned Presets to discover valid values and the required audio sample rate. |
enableEndpointDetection |
2 |
boolean |
Optional | false |
Enable endpoint detection for the recognition engine. |
online_speaker_diarization_settings |
3 |
OnlineSpeakerDiarizationSettings |
Optional | Unset | Online speaker-diarization configuration. |
ai_summaries_request |
5 |
SpeechRecognitionHeaderSummariesRequest |
Optional | Unset | Summaries to request for the completed Desktop session. |
is_transient_session |
6 |
boolean |
Optional | false |
Mark the session as transient. |
enable_itn |
7 |
boolean |
Optional | false |
Apply server FST ITN, unless the selected model already supplies ITN. |
enable_word_mappings |
8 |
boolean |
Optional | false |
Apply the authenticated user's saved mappings and standard dictation commands. |
Protobuf field 4 is reserved and must not be used.
OnlineSpeakerDiarizationSettings
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
enabled |
1 |
boolean |
Optional | false |
Enable online speaker diarization. |
max_speakers |
2 |
int32 |
Optional | 0 |
Maximum expected speakers. Set -1 for automatic speaker-count detection. An omitted field decodes to the protobuf default 0. |
SpeechRecognitionHeaderSummariesRequest
| Field | Protobuf field | Type | Default | Description |
|---|---|---|---|---|
summary_prompt_template_uuids |
1 |
repeated string |
Empty list | UUIDs of summary prompt templates available to the user. |
additional_metadata |
2 |
map<string, string> |
Empty map | Additional summary context accepted by the current context catalog. |
SpeechRecognitionPacket
| Field | Protobuf field | Type | Default | Description |
|---|---|---|---|---|
buffer |
1 |
bytes |
Empty bytes | Raw signed 16-bit little-endian mono PCM audio at the assigned preset's sample rate. This is the packet oneof variant. |
Use short audio packets suitable for live streaming. A packet is wrapped in SpeechRecognitionPacket, then in SpeechRecognitionRequest; the WebSocket binary message contains the serialized outer request.
Server binary messages
Every server binary message is one serialized Api.SpeechRecognitionResponse protobuf message. Decode the complete WebSocket message directly, without removing a length prefix.
SpeechRecognitionResponse
| Field | Protobuf field | Type | Default | Description |
|---|---|---|---|---|
result |
1 |
SpeechSessionResult |
Unset | Partial or final recognition result. |
info |
2 |
SpeechSessionInfo |
Unset | Session information sent after the header is accepted and recognition starts. |
Exactly one response oneof variant is set in each server binary message.
SpeechSessionInfo
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
session_history_uuid |
1 |
string |
Optional | Empty string | UUID of the Desktop session. Use it with the Sessions and Recordings API. |
SpeechSessionResult
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
hypotheses |
1 |
Hypothesis[] |
Repeated | Empty list | Recognition hypotheses, ordered by preference. |
partial |
2 |
boolean |
Required | - | true for an interim result that can change; false for a finalized segment. |
asr_session_words_count |
3 |
int32 |
Optional | Unavailable when omitted | Cumulative finalized ASR words for this session, before filtering and text processing. |
Hypothesis
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
transcript |
1 |
string |
Required | - | Recognized text. |
words |
2 |
Word[] |
Repeated | Empty list | Word-level timing and confidence. |
confidence |
3 |
float |
Required | - | Hypothesis confidence score. |
Word
| Field | Protobuf field | Type | Presence | Default | Description |
|---|---|---|---|---|---|
word |
1 |
string |
Required | - | Recognized word token. |
punctuation |
2 |
string |
Optional | Empty string | Punctuation associated with the word. |
startSeconds |
3 |
float |
Required | - | Word start time in seconds from the beginning of the stream. |
endSeconds |
4 |
float |
Required | - | Word end time in seconds from the beginning of the stream. |
confidence |
5 |
float |
Required | - | Word confidence score. |
speaker_tag |
6 |
int32 |
Optional | 0 when unset |
Speaker tag when diarization is active. Assigned tags start at 1; use protobuf presence to distinguish an unset tag. |
Server text messages
completed
Sent after complete when all buffered audio and final results have been processed. The server then closes the WebSocket with close code 1000.
| Field | Type | Nullable | Description |
|---|---|---|---|
type |
string |
No | Always completed. |
requestId |
string |
No | Identifier for support and log correlation. |
error
Sent when authentication, message ordering, validation, capacity, or recognition fails. After this message, the server closes the connection.
| Field | Type | Nullable | Description |
|---|---|---|---|
type |
string |
No | Always error. |
code |
string |
No | Machine-readable status code. |
message |
string |
No | Safe human-readable failure description. |
requestId |
string |
No | Identifier for support and log correlation. |
{
"type": "error",
"code": "FAILED_PRECONDITION",
"message": "The first recognition message must contain a header",
"requestId": "ws-2df8573e"
}
Common status codes:
| Code | Description |
|---|---|
UNAUTHENTICATED |
Authentication is missing, invalid, or has not completed before another message. |
PERMISSION_DENIED |
Desktop access is unavailable or the requested preset is not assigned to the user. |
INVALID_ARGUMENT |
A control message, tenant UUID, protobuf message, or summary context is invalid. |
FAILED_PRECONDITION |
Messages were sent out of order or input was already completed. |
RESOURCE_EXHAUSTED |
The simultaneous Desktop recognition-session limit was reached. |
UNAVAILABLE |
A recognition engine or required service is temporarily unavailable. |
ABORTED |
The active recognition engine stream failed. |
INTERNAL |
Recognition could not be started or completed. |
Client, authentication, permission, and ordering errors close with WebSocket code 1008. Capacity and temporary-availability errors close with 1013; other server failures close with 1011. A client or network disconnect before completed cancels the Desktop recognition session; no terminal text message can be delivered over an already closed connection.
During a planned service shutdown, active recognition connections are allowed to finish until the configured drain deadline. New connections receive 503 Service Unavailable, or an upgraded connection caught during shutdown receives UNAVAILABLE and closes with code 1013. Clients can reconnect to another available instance.
Message limits
| Client message kind | Default maximum | Description |
|---|---|---|
| Text control message | 16,384 bytes |
Applies independently to authenticate and complete. |
| Binary protobuf message | 4,194,304 bytes |
Applies to each serialized SpeechRecognitionRequest. |
An installation can configure different limits. Keep authentication messages small, split audio across packet messages, and allow room for recognition headers containing summary metadata. A message rejected by the WebSocket transport for exceeding a limit may close without a protocol error message.
Browser serialization outline
Use generated protobuf bindings for Api.SpeechRecognitionRequest and Api.SpeechRecognitionResponse. The method names depend on the selected protobuf generator; the wire steps remain the same:
socket.addEventListener("open", () => {
socket.send(JSON.stringify({
type: "authenticate",
authentication: { token: accessToken },
}));
socket.send(SpeechRecognitionRequest.create({
header: {
presetName: "general-he",
enableEndpointDetection: true,
},
}).toBinary());
});
socket.addEventListener("message", async (event) => {
if (event.data instanceof Blob) {
const response = SpeechRecognitionResponse.fromBinary(
new Uint8Array(await event.data.arrayBuffer()),
);
handleRecognitionResponse(response);
return;
}
const control = JSON.parse(event.data);
if (control.type === "completed") {
console.log("Recognition completed", control.requestId);
} else if (control.type === "error") {
console.error(control.code, control.message, control.requestId);
}
});
Voice Studio dictation always sends enable_itn=true and enable_word_mappings=true; these options have no Studio controls. Meeting mode sends both as false. API defaults remain false when omitted.
Set socket.binaryType = "arraybuffer" if the client should receive binary messages as ArrayBuffer instead of Blob.