Self-hosted voice: signaling to speech
Same feature, a second implementation. Instead of routing microphone audio through a managed media cloud and hosted speech APIs, this path runs the media server, speech recognition, and speech synthesis on my own VPS. The permission-checked resolver and fixed workspace views underneath are unchanged, only how the audio gets there and back is different.
Two ways to wire the same feature
Both backends are live. Rooms are tagged so a session lands on one implementation or the other, and either way it reaches the same resolver, the same access rules, and the same set of workspace views.
Signaling, media, and the speech hop
Signaling, the media server, and its relay all run on one self-hosted VPS behind a tunnel. Control traffic always takes one path; audio takes whichever of two paths ICE negotiation settles on for that session, not both at once.
Signaling, always tunneled
Room join, ICE candidate exchange, and worker control events ride one tunnel as HTTPS/WSS regardless of network conditions.
Media, whichever path wins
Audio takes direct UDP when the client's NAT allows it, or falls back to the media server's built-in TURN relay over TLS on 443 for CGNAT and locked-down networks. A session sticks to one path for its whole duration.
One worker, both directions
faster-whisper turns incoming speech into text, and Kokoro TTS turns the assistant's reply back into an outbound audio track, so both legs of the conversation stay on infrastructure I run.
Why self-host this layer
No per-call speech fees
faster-whisper and Kokoro TTS run on my own VPS instead of metered cloud APIs, so cost stops scaling with every utterance.
One less provider boundary
Audio and transcript text don't have to leave infrastructure I run for the speech step, on top of the same short-lived, permission-checked room grants.
A second real implementation
Building and running both versions is the point: the same feature proven two different ways, not a rewrite that throws the first one away.
Privacy and failure boundaries
The same content-free diagnostics apply here as on the managed-cloud path. Room names, tokens, credentials, raw audio, transcript text, parsed commands, and provider responses stay out of logs. Short-lived grants limit what the browser can publish, and the backend rechecks every request before a workspace view is selected, regardless of which voice backend the room is tagged for.