Skip to content

Screen sharing relay

The screen-share relay (technically a Selective Forwarding Unit, or SFU) is a small service inside the server that takes one screen- share upload from a broadcaster and fans it out to every viewer without the broadcaster doing extra work.

Without the relay, screen sharing still works on a local network, but falls back to peer-to-peer, which is unreliable behind strict NAT or across the internet.

Fancy Mumble ServerSFUUDP 10000BroadcasterViewer 1Viewer 2Viewer NBroadcaster sends once.Server forwards to every viewer.1× uploadfan-outfan-outfan-out
  • You have more than two or three viewers for a typical share.
  • Your users are spread across the internet.
  • Some users sit behind corporate NAT or carrier-grade NAT.

If you only ever do 1-on-1 calls on the same network, you may not need it.

ports:
- "10000:10000/udp"
environment:
MUMBLE_CONFIG_WEBRTCSFUENABLED: true
MUMBLE_CONFIG_WEBRTCSFUPORT: 10000
MUMBLE_CONFIG_WEBRTCSFUPUBLICIP: "203.0.113.5"
KeyDefaultDescription
webrtcsfuenabledfalseMaster toggle.
webrtcsfuport10000UDP port the relay listens on.
webrtcsfupublicip127.0.0.1Address that viewers use to reach the relay. Must be reachable.
webrtcsfumodulepath(built-in)Override if you want a custom relay binary.
  1. UDP port 10000 is open in the firewall (or whatever you set webrtcsfuport to).
  2. UDP port 10000 is forwarded from your router to the server (home setups).
  3. The public IP your server advertises matches the one the internet can reach. Check with curl -s https://ifconfig.me from the server.

After a restart, the logs should include:

webrtc-sfu: listening on 0.0.0.0:10000/udp (public 203.0.113.5)

Then ask two clients to test:

  1. Client A starts a screen share.
  2. Client B should see a thumbnail in the stream grid.
  3. If B sees a black thumbnail, the data path is broken. Check the public IP and the firewall first.
Fancy Mumble ServerWebRTC SFUport 10000 UDPreceives one uploadfans out to all viewersBroadcasterstreams desktopto channel viewersViewer Aindependent streamViewer Bindependent streamViewer Cindependent streamBroadcaster upload is constant regardless of viewer count.The SFU handles every viewer independently.TCP 64738 · control / signalingUDP 10000 · one uploadUDPUDPUDP
  • The broadcaster’s app uploads one stream to the relay over UDP.
  • The relay fans the stream out to every viewer independently.
  • All the signaling (ICE negotiation, offer/answer) travels over the existing TCP voice/control port. The relay only carries media.
  • The broadcaster’s upload bandwidth stays constant regardless of viewer count - that is the whole point.

Optional: behind a reverse proxy (nginx / Traefik / Caddy)

Section titled “Optional: behind a reverse proxy (nginx / Traefik / Caddy)”

A reverse proxy in front of the server is a common setup for TLS termination or port consolidation. Two ports are involved and they behave differently:

PortProtocolProxy support
64738 (voice/control)TCPStandard TCP/HTTP proxy
10000 (SFU media)UDPNeeds explicit UDP forwarding

The TCP side (signaling) passes through any standard TCP proxy with no special config. The UDP side requires the proxy to support raw UDP forwarding - not every proxy does by default.

nginx’s stream {} block handles raw TCP and UDP. Add it alongside your http {} block in nginx.conf:

stream {
server {
listen 10000 udp;
# Replace with the address of the host running mumble-server.
proxy_pass 127.0.0.1:10000;
proxy_timeout 10s;
proxy_responses 1;
}
}

Tell the SFU to advertise the proxy’s public IP, not the server’s internal address:

environment:
MUMBLE_CONFIG_WEBRTCSFUPUBLICIP: "203.0.113.5" # proxy public IP

The http {} side (TLS termination, WebSocket for the control port) uses a standard proxy_pass directive and is not shown here.

If webrtcsfuenabled=false (or the library is missing), the app falls back to direct peer-to-peer for screen sharing:

  • Works fine on a local network.
  • Works for two clients with no NAT.
  • Often fails behind strict NAT.
  • Broadcaster’s upload scales linearly with viewer count.

A modest virtual server can host a relay for a few dozen viewers. For heavier use:

  • Each 720p stream is about 1 to 2 Mbps. Multiply by viewer count.
  • A 1 vCPU virtual server can handle around 20 to 30 viewer streams.
  • For a busy server, run the relay on a separate node and point webrtcsfupublicip at that node.

If your users sit behind extremely strict firewalls (some corporate networks, mobile carriers), even the relay may not be reachable on UDP 10000. The next step is a TURN server that relays media over 443/TCP. Fancy Mumble does not yet ship a built-in TURN, but you can point clients at any standard TURN by setting their STUN/TURN config.

environment:
MUMBLE_CONFIG_WEBRTCSFUENABLED: false

Existing streams stop immediately on restart. Clients fall back to peer-to-peer.

  • Black thumbnails: public IP is wrong or unreachable.
  • Logs say “library not found”: the SFU binary was not built into your image. Either rebuild with the relay enabled (see Building from source) or use the official image.
  • One-way streams: ICE could not pick a candidate. Check the client’s WebRTC stats from Expert mode.

Continue with File server.