Skip to content

WebRTC Configuration

WebRTC is used for real-time low-latency client communication. SyncTV handles signaling, permission checks, and ICE server delivery.

Allowed values:

  • signaling_only
  • peer_to_peer

SyncTV only relays signaling and does not provide built-in STUN.

Use it when you already have WebRTC infrastructure or do not want SyncTV to expose a UDP STUN port.

Enables P2P mode and can use built-in STUN plus external ICE servers.

Default:

webrtc:
mode: "peer_to_peer"

webrtc.enable_builtin_stun default: true.

STUN helps clients discover their public mapped address for NAT traversal.

Disable it when:

  • You use external STUN/TURN infrastructure.
  • The deployment cannot expose UDP.
  • You only use signaling_only.

webrtc.stun_port default: 3478.

Expose UDP 3478 if clients should use the built-in STUN server.

webrtc.stun_host default:

webrtc:
stun_host: "0.0.0.0"

Container and server deployments usually keep this default.

Address advertised to clients for the STUN server.

If empty, SyncTV tries server.advertise_host:stun_port, STUN_EXTERNAL_IP, and cloud metadata. The built-in STUN server starts only when a public routable address is found; otherwise SyncTV skips built-in STUN.

Set it explicitly in NAT or Kubernetes environments to a client-reachable public ip:port or DNS name, such as a LoadBalancer IP, node public IP, or STUN hostname. Do not use a Pod IP or ClusterIP Service IP.

webrtc:
stun_external_addr: "203.0.113.10:3478"

or:

webrtc:
stun_external_addr: "stun.example.com:3478"

Default: false.

Filters private, loopback, and link-local ICE candidates to reduce internal network information exposure.

The default allows direct same-device and LAN connections for self-contained deployments. Enable filtering when every client has a usable public STUN or TURN candidate and hiding local network addresses is required.

External ICE servers are managed through runtime settings, not static YAML:

webrtc.external_ice_servers

Value format:

[
{ "urls": ["stun:stun.l.google.com:19302"] },
{
"urls": ["turn:turn.example.com:3478"],
"username": "user",
"credential": "pass"
}
]

Runtime settings are used because TURN credentials may rotate and administrators may need to adjust ICE servers without restarting the service.

Voice calls currently use a room-scoped WebRTC Mesh. Each participant creates PeerConnections to the other N-1 participants, so client upload and total room connection count grow quickly. webrtc.maxVoiceParticipantsPerRoom defaults to 8 and can be changed dynamically from 2 through 32 in runtime settings.

The server atomically reserves a slot during voice join. Lowering the limit affects subsequent joins while existing calls continue; leave, disconnect, and session expiry release slots. Multi-replica deployments use Redis to coordinate a global room count.

Large rooms should use an SFU architecture: each client sends one Opus uplink, and the SFU forwards a bounded set of downlink tracks based on active speakers and subscription priority. This keeps client upload fixed at one stream and centralizes bandwidth, speaking-permission, and room-capacity policy.

Room administrators control voice and media P2P independently through voiceChatEnabled and p2pMediaEnabled. Updates use the existing versioned room-settings fanout across replicas and clients. Disabling a capability immediately releases voice slots and media swarms registered by each connection. Subsequent joins, offers, answers, ICE candidates, and swarm joins return a permission-class error. Clients observe room_settings, destroy local PeerConnections, tracks, DataChannels, and the P2P gateway when disabled, and hide the corresponding controls.

If WebRTC connectivity fails, check:

  1. Clients can reach the SyncTV HTTP/gRPC API.
  2. UDP 3478 is reachable when built-in STUN is enabled.
  3. stun_external_addr is reachable by clients and is not a Pod IP, ClusterIP, loopback, or private address unless you disable built-in STUN and rely on external ICE/TURN.
  4. Reverse proxies only handle HTTP and do not automatically expose UDP.
  5. TURN is configured for strict NAT environments.
  6. filter_private_ice_candidates matches your network model.