Why CGO?
Voxray uses thegopus Go binding to encode raw PCM audio into Opus frames for delivery over WebRTC data channels and tracks. gopus wraps libopus, a C library, which means the Go toolchain must invoke a C compiler during the build — this is what CGO enables.
Without CGO:
- The server can receive WebRTC connections and decode inbound audio (speech from the user).
- The server cannot encode TTS audio into Opus frames, so it has no way to send synthesized speech back to the browser over the peer connection.
- The server returns 503 on
/webrtc/offerto prevent silent audio failures.
make build-voice):
- The Opus encoder is compiled into the binary.
- TTS audio is encoded in real time and delivered as Opus RTP over the WebRTC peer connection.
- Full duplex voice works: the browser sends microphone audio, the pipeline runs STT → LLM → TTS, and synthesized speech arrives back in the browser.
Step 1: Install the CGO Toolchain
You need a C compiler on your PATH before building. Choose your OS:- macOS
- Linux
- Windows
macOS ships Clang as part of Xcode Command Line Tools. Install or confirm:If the tools are already installed, this exits immediately. Verify the compiler is accessible:No additional packages are needed — Clang satisfies CGO’s C compiler requirement.
Step 2: Clone the Repository
If you have not cloned the repository yet:Step 3: Configure for WebRTC
Copy the example config and open it for editing:transport to "smallwebrtc" to enable WebRTC only, or "both" to enable WebSocket and WebRTC simultaneously. Add at least one STUN server under webrtc_ice_servers so ICE candidates can be gathered:
"transport": "smallwebrtc" enables only the /webrtc/offer endpoint. "transport": "both" activates both /ws (WebSocket) and /webrtc/offer (WebRTC) simultaneously, which is useful during development to support both client types.Step 4: Build with Voice Support
Run the voice build target, which enables CGO and compiles the Opus encoder into the binary:CGO_ENABLED=1 go build -o voxray ./cmd/voxray. Confirm the build succeeded:
Step 5: Run the Server
Step 6: Connect via Browser
Voxray ships a browser test client undertests/frontend/. Serve it locally with Python’s built-in HTTP server:
- In the Server URL field, enter
http://localhost:8080. - Click Start (or the microphone button).
- Accept the browser microphone permission prompt.
- Speak — the pipeline runs STT → LLM → TTS and plays synthesized speech back through the WebRTC peer connection.
SDP Signaling for Non-Browser Clients
For native apps, CLIs, or server-to-server integrations, use the/webrtc/offer REST endpoint directly.
Send an SDP offer:
answer field contains the SDP answer string. Set this as the remote description on your peer connection to complete the offer/answer exchange, then proceed with ICE candidate exchange.
For runner-style clients (which create a named session before offering SDP), use the two-step flow:
Troubleshooting
cgo: C compiler ... not found
The build fails because no C compiler is on your PATH.
gcc --version or clang --version returns output before re-running make build-voice.
ICE connection fails — no audio after signaling completes
The SDP exchange succeeds (you receive an answer) but the WebRTC peer connection never transitions toconnected and no audio flows.
Common causes and fixes:
- Missing or unreachable STUN server: Confirm
webrtc_ice_serversis set inconfig.jsonand thatstun.l.google.com:19302is reachable from your network. Trync -u stun.l.google.com 19302to verify UDP connectivity. - Symmetric NAT / firewall blocking UDP: STUN alone cannot traverse all NAT types. Add a TURN relay server to
webrtc_ice_servers. - Server behind a non-public IP: If Voxray is on a private network and the browser is on a different network, ICE candidates advertised by the server are non-routable. Use a TURN server or place the server on a public IP.
opus encode error or opus encoder unavailable (build without cgo)
The server binary was built without CGO. The Opus encoder is not compiled in.
make build-voice (not make build). After rebuilding, restart the server and retry the WebRTC connection.
Browser says “Permission denied” for microphone
The page is served over plain HTTP from a non-localhost origin. Browsers restrict microphone access to secure origins (HTTPS or localhost). Fix: Either run everything locally (localhost) for development, or serve the frontend over HTTPS and configure Voxray behind a TLS-terminating reverse proxy (nginx, Caddy, etc.) with a valid certificate.
Next Steps
Installation
Full installation guide including OS-specific Go setup and Docker.
Configuration Reference
All config fields for transports, ICE servers, providers, and more.
Connectivity Guide
Understand all entry points: WebSocket, WebRTC, runner, Daily.co, and telephony.
Supported Providers
Switch STT, LLM, or TTS provider with a single config change.