Voice & Video Calls
Chatto supports real-time voice and video calls inside rooms using LiveKit, an open-source WebRTC media server. When enabled, any room member can start or join a call directly from the room header.
How It Works
Section titled “How It Works”LiveKit runs as a separate service alongside Chatto. Chatto handles authentication and call state, while LiveKit handles the WebRTC media transport:
- A user joins the call from the room header.
- Chatto verifies the user’s room membership and generates a short-lived LiveKit JWT token.
- The user’s browser connects directly to the LiveKit server using the token and a per-call E2EE key from Chatto.
- Other room members see active call indicators update in real time.
Calls are implicit — there’s no “start call” action. The first person to join creates the call and a fresh E2EE key; when the last person leaves, the call ends and Chatto shreds that key.
Chatto records call start/join/leave/end facts durably and reconciles active participants against LiveKit webhooks, so call indicators recover after server restarts. Room history shows when a call starts and when the active call ends; individual participant joins and leaves update the active call UI without appearing as timeline messages. LiveKit media is end-to-end encrypted by current Chatto clients; older clients that do not support this call encryption cannot decode encrypted media.
Requirements
Section titled “Requirements”- A running LiveKit server (self-hosted or cloud)
- An API key and secret configured on both the LiveKit server and Chatto
-
Install and run LiveKit
For local development, the quickest option is the LiveKit CLI:
Terminal window # macOSbrew install livekit# Then run in dev modelivekit-server --devThis starts LiveKit on
ws://localhost:7880with a default API key ofdevkeyand secret ofsecret.For production, see the LiveKit self-hosting guide.
-
Configure Chatto
Add a
[livekit]section to yourchatto.toml:[livekit]enabled = trueurl = 'ws://localhost:7880'api_key = 'devkey'api_secret = 'secret'[livekit]enabled = trueurl = 'wss://livekit.example.com'api_key = 'your-api-key'api_secret = 'your-api-secret'# webhook_url = 'https://chatto.example.com/webhooks/livekit' # defaults to {webserver.url}/webhooks/livekitOr use environment variables:
Terminal window CHATTO_LIVEKIT_ENABLED=trueCHATTO_LIVEKIT_URL=wss://livekit.example.comCHATTO_LIVEKIT_API_KEY=your-api-keyCHATTO_LIVEKIT_API_SECRET=your-api-secret# CHATTO_LIVEKIT_WEBHOOK_URL=https://chatto.example.com/webhooks/livekit # defaults to {webserver.url}/webhooks/livekit -
Configure LiveKit webhooks
LiveKit must send webhook events to Chatto so it can track who’s in a call. Add the webhook URL to your LiveKit server config (
livekit.yaml):webhook:urls:- https://chatto.example.com/webhooks/livekitapi_key: your-api-keyFor local development with
livekit-server --dev, the--devflag disables webhooks. That is useful for testing local media connectivity, but active-call indicators and participant reconciliation require webhook delivery in normal deployments. -
Restart Chatto
Calls will be available immediately. Call controls appear in room headers when LiveKit is configured.
Production Considerations
Section titled “Production Considerations”- Network: Users connect directly to the LiveKit server from their browsers. Make sure your LiveKit server is reachable from the public internet (or your private network, for internal deployments).
- TURN/STUN: LiveKit includes a built-in TURN server for NAT traversal. For restrictive networks, you may need to configure it to listen on port 443.
- Scaling: A single LiveKit server handles hundreds of concurrent participants for typical small deployments. For larger deployments, LiveKit supports multi-node clustering with Redis.
- End-to-end encryption: Chatto enables LiveKit E2EE automatically for clients. No additional LiveKit server configuration is required.
- API Secret: Keep your API secret confidential. It’s used to sign JWT tokens and should never be exposed to clients.
Features
Section titled “Features”- Mute/unmute — Toggle your microphone during a call
- Audio device selection — Switch between microphones without leaving the call
- Camera toggle — Turn your camera on and off during a call
- Video device selection — Switch between cameras without leaving the call
- Active call indicators — Rooms with active calls show a call indicator in the room list
- Audio level visualization — Participant avatars pulse with accent-colored rings based on speaking volume
- Call history notices — Room history shows when a call starts and when the active call ends
Disabling Voice & Video Calls
Section titled “Disabling Voice & Video Calls”To disable voice and video calls, either remove the [livekit] section from chatto.toml or set:
[livekit]enabled = falseWhen disabled, call controls are hidden and all call API endpoints return null.