Godot
aurix_voice GDExtension for Godot 4.3+ — native UDP/QUIC client on desktop and mobile, a GDScript client on the same API for web exports.
Install#
Unzip aurix-godot-addon-1.13.0.zip from the release into your project's addons/ (it contains addons/aurix_voice with the prebuilt GDExtension for Windows, Linux, macOS and Android plus the web client). Godot 4.3 or newer.
Connect and join#
var voice := AurixVoiceClient.new() # AurixWebVoiceClient in web exports — same calls and signals
add_child(voice)
voice.session_ready.connect(_on_session_ready)
voice.participant_speaking.connect(_on_speaking)
voice.request_failed.connect(func(_rid, code, msg): push_warning(code + ": " + msg))
if voice.connect_to_server(token.endpoint.ws_url, token.token) != AurixVoiceClient.RESULT_OK:
push_error(voice.get_last_error())
func _on_session_ready(_session: Dictionary) -> void:
voice.join_channel(token.channels[0].channel_id) # returns the request id; capture starts automatically (auto_capture)connect_to_server returns a result code and join_channel the request id; results arrive as signals (session_ready, channel_joined, participant_joined, participant_left, participant_speaking, recovering, recovered, disconnected).
Positional audio#
func _physics_process(_d: float) -> void:
voice.update_transforms(channel_id, { my_user_id: player.global_transform }) # or update_positions(channel_id, [...])By default the client plays a server-panned mix. For Godot-side spatialisation add an AurixParticipantPlayer (an AudioStreamPlayer3D) under each remote avatar with user_id set — the player claims that participant's stream and your attenuation, buses and reverb apply.
Push-to-talk, mute, devices#
voice.set_push_to_talk_action("ptt") # or voice.set_muted(...) yourself
voice.set_input_gain(1.0)
voice.set_vad_threshold(0.02)
# capture: the client records from Godot's input device (AudioServer.input_device) through an AudioEffectCapture bus;
# set auto_capture = false and call push_capture() to feed PCM yourselfExports#
- Desktop and mobile exports use the native client: AURX over UDP (QUIC optional) with a TLS tunnel fallback; microphone permission on Android/iOS as usual.
- Web exports use
AurixWebVoiceClienton top of the Web SDK (WebTransport → WebRTC → WebSocket); the page must be served over HTTPS for microphone access, and the browser owns capture (set_input_device,enumerate_devices).
Channel patterns#
| Pattern | Channels per player | Notes |
|---|---|---|
| Co-op / squad | one team | mute = PTT off; nothing positional |
| Shooter with proximity | positional (shard) + team (squad) | transmit on the team channel by default, hold a key to speak locally |
| Open world | positional (shard), optional whisper for direct calls | roster_radius keeps the participant list small |
| Event / stage | audience-shaped channel, hosts with priority | thousands of listeners, a few speakers |
The transmit channel is a client-side choice: join several, send to one, hear all with receive. Positional audio needs positions roughly 10 times a second; between updates the node interpolates.
Latency and quality#
Expect 30–60 ms mouth-to-ear on the same continent over QUIC, more over TURN. Opus runs at 32 kbps with DTX by default; the spending ladder may lower it to 16 kbps when your forecast exceeds the limit. Server-side noise suppression is on by default and costs nothing on the client.
Testing without a full build#
- Two players: the rooms demo in a browser plus your build — they share a cell, so a token from your backend joins the same channel by name.
- Mic path: an
echochannel plays your own voice back through the real pipeline. - Network: throttle UDP on one machine and watch the transport fall back to WebRTC / WebSocket in the SDK's connection state.
Troubleshooting#
| Symptom | Check |
|---|---|
| connected, no audio | capture started? channel grant speak/receive? OS microphone permission? |
| audio but no spatialisation | positions sent on the positional channel id, not the team channel |
| random drops on mobile | the SDK pauses capture in the background by design; resume on foreground |
QUOTA_EXCEEDED on connect | plan concurrency cap or spending ladder step 4 — see Spending limit |