Voice Events
VOICE_STATE_UPDATE
VOICE_STATE_UPDATESent when a user's voice state changes (join, leave, mute, deafen, screen share), with the whole state. Broadcast to all members of the space, or of the conversation for calls. A VOICE_SYNC that changes nothing sends none. Updates can arrive out of order: apply one only if its version is greater than the last one applied for that user and room, counting the versions in SPACE_CREATE voice_states and READY active_calls.
| Field | Type | Description |
|---|---|---|
room_id | string | Voice room ID |
user_id | string | User whose voice state changed |
joined | boolean | Whether the user is in the voice room |
muted | boolean | Whether the user is muted: what their client last sent in VOICE_SYNC, but always true without SpeakInVoice (false when joined is false) |
deafened | boolean | Whether the user is deafened (false when joined is false) |
screen_sharing | boolean | Whether the user is screen sharing (false when joined is false) |
version | integer | Grows with every voice change, across rooms and gateway restarts; a safe JavaScript integer |
{
"type": "VOICE_STATE_UPDATE",
"data": {
"room_id": "019cf96a-be82-72c5-830f-75e85355d800",
"user_id": "019cf96a-3d5b-72c5-830f-75e85355d078",
"joined": true,
"muted": false,
"deafened": false,
"screen_sharing": false,
"version": 1792181390951042
}
}VOICE_SESSION_REPLACED
VOICE_SESSION_REPLACEDSent to a user when their voice session ends server-side: it was replaced by a new connection (e.g., connecting from another device), or they lost ViewChannels or JoinVoice in that room, left the space, or the room was deleted or is no longer a voice room. If the session that joined is gone (the client reconnected), it is sent to all of the user's sessions; only one that is in that room should act on it. The client should clean up its local voice state. Losing SpeakInVoice does not end the session; the gateway stops forwarding the user's audio and shows them as muted (VOICE_STATE_UPDATE). When they get it back, it shows the mute state their client last sent in VOICE_SYNC again. Clients mute themselves when they lose it, and should send that VOICE_SYNC too.
| Field | Type | Description |
|---|---|---|
room_id | string | Voice room ID where the session ended |
reason ? | string | "permissions" when the user lost access to the room; absent when the session was replaced |
{
"type": "VOICE_SESSION_REPLACED",
"data": {
"room_id": "019cf96a-be82-72c5-830f-75e85355d800",
"reason": "permissions"
}
}VOICE_JOINED
VOICE_JOINEDSent to the user after they successfully join a voice room. Contains the SDP answer from the server to complete the WebRTC handshake.
| Field | Type | Description |
|---|---|---|
room_id | string | Voice room ID |
answer | RTCSessionDescription? | SDP answer from the server (always set) |
{
"type": "VOICE_JOINED",
"data": {
"room_id": "019cf96a-be82-72c5-830f-75e85355d800",
"answer": {
"type": "answer",
"sdp": "v=0\r\no=- 1234567890 2 IN IP4 127.0.0.1..."
}
}
}WEBRTC_ICE_CANDIDATE
WEBRTC_ICE_CANDIDATESent when the server discovers a new ICE candidate for the WebRTC connection. The client should add this candidate to its peer connection.
| Field | Type | Description |
|---|---|---|
candidate | string | ICE candidate string |
room_id | string | Voice room ID |
{
"type": "WEBRTC_ICE_CANDIDATE",
"data": {
"candidate": "candidate:1 1 UDP 2130706431 192.168.1.1 12345 typ host",
"room_id": "019cf96a-be82-72c5-830f-75e85355d800"
}
}WEBRTC_RENEGOTIATE
WEBRTC_RENEGOTIATESent by the server when the WebRTC connection needs to be renegotiated (e.g., when another user joins or leaves the voice room). Contains a new SDP offer that the client must respond to with an answer.
| Field | Type | Description |
|---|---|---|
offer | RTCSessionDescription | New SDP offer from the server |
room_id | string | Voice room ID |
{
"type": "WEBRTC_RENEGOTIATE",
"data": {
"offer": {
"type": "offer",
"sdp": "v=0\r\no=- 1234567890 3 IN IP4 127.0.0.1..."
},
"room_id": "019cf96a-be82-72c5-830f-75e85355d800"
}
}WEBRTC_RENEGOTIATE_ANSWER
WEBRTC_RENEGOTIATE_ANSWERSent by the server as a confirmation after processing the client's renegotiation answer.
| Field | Type | Description |
|---|---|---|
room_id | string | Voice room ID |
answer | RTCSessionDescription? | SDP answer from the server (always set) |
{
"type": "WEBRTC_RENEGOTIATE_ANSWER",
"data": {
"room_id": "019cf96a-be82-72c5-830f-75e85355d800",
"answer": {
"type": "answer",
"sdp": "v=0\r\no=- 1234567890 4 IN IP4 127.0.0.1..."
}
}
}