WebRTC Configuration
This page describes how to configure WebRTC settings inside neko.
Neko uses WebRTC with the Pion library to establish a peer-to-peer connection between the client and the server. This connection is used to stream audio, video, and data bidirectionally between the client and the server.
ICE Setup
ICE, which stands for Interactive Connectivity Establishment, is a protocol used to find the best path to connect peers, such as a client and a server. It helps discover the public IP addresses and ports of both parties to establish a direct connection. ICE candidates, which contain this information, are exchanged through a signaling server to facilitate the connection process.
ICE Trickle
ICE Trickle is a feature that allows ICE candidates to be sent as they are discovered, rather than waiting for all candidates to be discovered before sending them. It means that the ICE connection can be established faster as the server can start connecting to the client as soon as it has a few ICE candidates and doesn't have to wait for all of them to be discovered.
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_ICETRICKLE=true
--webrtc.icetrickle true
webrtc:
icetrickle: true
ICE Lite
ICE Lite is a minimal implementation of the ICE protocol intended for servers running on a public IP address. It is not enabled by default to allow more complex ICE configurations out of the box.
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_ICELITE=false
--webrtc.icelite false
webrtc:
icelite: false
When using ICE Servers, ICE Lite must be disabled.
ICE Servers
ICE servers are used to establish a connection between the client and the server. There are two types of ICE servers:
- STUN: A STUN server is used to discover the public IP address of the client. This is used to establish a direct connection between the client and the server.
- TURN: A TURN server is used to relay data between the client and the server if a direct connection cannot be established.
The configuration of a single ICE server is defined by the following fields:
Field | Description | Type |
---|---|---|
urls | List of URLs of the ICE server, if the same server is available on multiple URLs with the same credentials, they can be listed here. | string[] |
username | Username used to authenticate with the ICE server, if the server requires authentication. | string |
credential | Credential used to authenticate with the ICE server, if the server requires authentication. | string |
- YAML
- JSON
- urls: "turn:<MY-COTURN-SERVER>:3478"
username: "neko"
credential: "neko"
- urls: "stun:stun.l.google.com:19302"
[
{
"urls": "turn:<MY-COTURN-SERVER>:3478",
"username": "neko",
"credential": "neko"
},
{
"urls": "stun:stun.l.google.com:19302"
}
]
You can specify the ICE servers as a JSON string in the docker-compose.yaml
file using the NEKO_WEBRTC_ICESERVERS_FRONTEND
and NEKO_WEBRTC_ICESERVERS_BACKEND
environment variables.
NEKO_WEBRTC_ICESERVERS_FRONTEND: |
[{
"urls": [ "turn:<MY-COTURN-SERVER>:3478" ],
"username": "neko",
"credential": "neko"
},{
"urls": [ "stun:stun.nextcloud.com:3478" ]
}]
The ICE servers are divided into two groups:
- YAML Configuration File
- Environment Variables
- Command Line Arguments
# STUN and TURN servers used by the frontend (array)
NEKO_WEBRTC_ICESERVERS_FRONTEND=<json encoded array>
# STUN and TURN servers used by the backend (array)
NEKO_WEBRTC_ICESERVERS_BACKEND=<json encoded array>
# STUN and TURN servers used by the frontend (array)
--webrtc.iceservers.frontend <json encoded array>
# STUN and TURN servers used by the backend (array)
--webrtc.iceservers.backend <json encoded array>
webrtc:
iceservers:
# STUN and TURN servers used by the frontend (array)
frontend: []
# STUN and TURN servers used by the backend (array)
backend: []
frontend
- ICE servers that are sent to the client and used to establish a connection between the client and the server.backend
- ICE servers that are used by the server to gather ICE candidates. They might contain private IP addresses or other sensitive information that should not be sent to the client.
Example with Coturn server in Docker Compose
services:
coturn:
image: 'coturn/coturn:latest'
network_mode: "host"
command: |
-n
--realm=localhost
--fingerprint
--listening-ip=0.0.0.0
--external-ip=<MY-COTURN-SERVER>
--listening-port=3478
--min-port=49160
--max-port=49200
--log-file=stdout
--user=neko:neko
--lt-cred-mech
Replace <MY-COTURN-SERVER>
with your LAN or Public IP address, and allow ports 49160-49200/udp
and 3478/tcp
. The --user
flag is used to specify the username and password for the TURN server. The --lt-cred-mech
flag is used to enable the long-term credentials mechanism for authentication. More information about the Coturn server can be found here.
Network Setup
Since WebRTC is a peer-to-peer protocol that requires a direct connection between the client and the server. This can be achieved by:
- Using a public IP address for the server (or at least reachable from the client if deployed on a private network).
- Using a TURN server to relay data between the client and the server if a direct connection cannot be established.
All specified ports along with the server's IP address will be sent to the client in ICE candidates to establish a connection. Therefore, it is important to ensure that the specified ports are open on the server's firewall, are not remapped to different ports, and are reachable from the client.
WebRTC does not use the HTTP protocol, therefore it is not possible to use nginx or other reverse proxies to forward the WebRTC traffic. If you only have exposed port 443
on your server, you must expose as well the WebRTC ports or use a TURN server.
There exist two types of connections:
- Ephemeral UDP port range: The range of UDP ports that the server uses to establish a connection with the client. Every time a new connection is established, a new port from this range is used. This range should be open on the server's firewall.
- UDP/TCP multiplexing: The server can use a single port for multiple connections. This port should be open on the server's firewall.
Ephemeral UDP port range
The ephemeral UDP port range can be configured using the following configuration:
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_EPR="59000-59100"
--webrtc.epr "59000-59100"
webrtc:
epr: "59000-59100"
The range 59000-59100
contains 101 ports, which should be open on the server's firewall. The server uses these ports to establish a connection with the client. You can specify a different range of ports if needed, with fewer or more ports, depending on the number of simultaneous connections you expect.
When specifying the ephemeral UDP port range in docker-compose.yaml
, make sure to use the same range for ports as UDP.
environment:
NEKO_WEBRTC_EPR: "59000-59100"
ports:
- "59000-59100:59000-59100/udp"
It is important to expose the same ports to the host machine, without any remapping e.g. 49000-49100:59000-59100/udp
instead of 59000-59100:59000-59100/udp
.
UDP/TCP multiplexing
The UDP/TCP multiplexing port can be configured using the following configuration:
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_UDPMUX=59000
NEKO_WEBRTC_TCPMUX=59000
--webrtc.udpmux 59000
--webrtc.tcpmux 59000
webrtc:
udpmux: 59000
tcpmux: 59000
The server uses only port 59000
for both UDP and TCP connections. This port should be open on the server's firewall. You can specify a different port if needed, or specify only one of the two protocols. UDP is generally better for latency, but some networks block UDP so it is good to have TCP available as a fallback.
When specifying the UDP/TCP multiplexing port in docker-compose.yaml
, make sure to correctly specify the protocol in the ports section.
environment:
NEKO_WEBRTC_UDPMUX: "59000"
NEKO_WEBRTC_TCPMUX: "59000"
ports:
- "59000:59000/udp"
- "59000:59000/tcp"
It is important to expose the same ports to the host machine, without any remapping e.g. 49000:59000/udp
instead of 59000:59000/udp
.
Server IP Address
The server IP address is sent to the client in ICE candidates so that the client can establish a connection with the server. By default, the server IP address is automatically resolved by the server to the public IP address of the server. If the server is behind a NAT, you want to specify a different IP address or use neko only in a local network, you can specify the server IP address manually.
NAT 1-to-1
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_NAT1TO1="10.10.0.5"
--webrtc.nat1to1 "10.10.0.5"
webrtc:
nat1to1: "10.10.0.5"
Currently, only one address can be specified. Therefore if you want to access your instance from both local and public networks, your router must support NAT loopback (hairpinning).
IP Retrieval URL
If you do not specify the server IP address, the server will try to resolve the public IP address of the server automatically.
- YAML Configuration File
- Environment Variables
- Command Line Arguments
NEKO_WEBRTC_IP_RETRIEVAL_URL="https://checkip.amazonaws.com"
--webrtc.ip_retrieval_url "https://checkip.amazonaws.com"
webrtc:
ip_retrieval_url: "https://checkip.amazonaws.com"
The server will send an HTTP GET request to the specified URL to retrieve the public IP address of the server.
Bandwidth Estimator
The bandwidth estimator is an experimental feature and might not work as expected.
The bandwidth estimator is a feature that allows the server to estimate the available bandwidth between the client and the server. It is used to switch between different video qualities based on the available bandwidth. The bandwidth estimator is disabled by default.
- YAML Configuration File
- Environment Variables
- Command Line Arguments
# enables debug logging for the bandwidth estimator (boolean)
NEKO_WEBRTC_ESTIMATOR_DEBUG=false
# how bigger the difference between estimated and stream bitrate must be to trigger upgrade/downgrade (float)
NEKO_WEBRTC_ESTIMATOR_DIFF_THRESHOLD=0.15
# how long to wait before downgrading again after previous downgrade (duration)
NEKO_WEBRTC_ESTIMATOR_DOWNGRADE_BACKOFF="10s"
# enables the bandwidth estimator (boolean)
NEKO_WEBRTC_ESTIMATOR_ENABLED=false
# initial bitrate for the bandwidth estimator (int)
NEKO_WEBRTC_ESTIMATOR_INITIAL_BITRATE=1000000
# passive estimator mode, when it does not switch pipelines, only estimates (boolean)
NEKO_WEBRTC_ESTIMATOR_PASSIVE=false
# how often to read and process bandwidth estimation reports (duration)
NEKO_WEBRTC_ESTIMATOR_READ_INTERVAL="2s"
# how long to wait for stable connection (upward or neutral trend) before upgrading (duration)
NEKO_WEBRTC_ESTIMATOR_STABLE_DURATION="12s"
# how long to wait for stalled bandwidth estimation before downgrading (duration)
NEKO_WEBRTC_ESTIMATOR_STALLED_DURATION="24s"
# how long to wait for stalled connection (neutral trend with low bandwidth) before downgrading (duration)
NEKO_WEBRTC_ESTIMATOR_UNSTABLE_DURATION="6s"
# how long to wait before upgrading again after previous upgrade (duration)
NEKO_WEBRTC_ESTIMATOR_UPGRADE_BACKOFF="5s"
# enables debug logging for the bandwidth estimator (boolean)
--webrtc.estimator.debug false
# how bigger the difference between estimated and stream bitrate must be to trigger upgrade/downgrade (float)
--webrtc.estimator.diff_threshold 0.15
# how long to wait before downgrading again after previous downgrade (duration)
--webrtc.estimator.downgrade_backoff "10s"
# enables the bandwidth estimator (boolean)
--webrtc.estimator.enabled false
# initial bitrate for the bandwidth estimator (int)
--webrtc.estimator.initial_bitrate 1000000
# passive estimator mode, when it does not switch pipelines, only estimates (boolean)
--webrtc.estimator.passive false
# how often to read and process bandwidth estimation reports (duration)
--webrtc.estimator.read_interval "2s"
# how long to wait for stable connection (upward or neutral trend) before upgrading (duration)
--webrtc.estimator.stable_duration "12s"
# how long to wait for stalled bandwidth estimation before downgrading (duration)
--webrtc.estimator.stalled_duration "24s"
# how long to wait for stalled connection (neutral trend with low bandwidth) before downgrading (duration)
--webrtc.estimator.unstable_duration "6s"
# how long to wait before upgrading again after previous upgrade (duration)
--webrtc.estimator.upgrade_backoff "5s"
webrtc:
estimator:
# enables debug logging for the bandwidth estimator (boolean)
debug: false
# how bigger the difference between estimated and stream bitrate must be to trigger upgrade/downgrade (float)
diff_threshold: 0.15
# how long to wait before downgrading again after previous downgrade (duration)
downgrade_backoff: "10s"
# enables the bandwidth estimator (boolean)
enabled: false
# initial bitrate for the bandwidth estimator (int)
initial_bitrate: 1000000
# passive estimator mode, when it does not switch pipelines, only estimates (boolean)
passive: false
# how often to read and process bandwidth estimation reports (duration)
read_interval: "2s"
# how long to wait for stable connection (upward or neutral trend) before upgrading (duration)
stable_duration: "12s"
# how long to wait for stalled bandwidth estimation before downgrading (duration)
stalled_duration: "24s"
# how long to wait for stalled connection (neutral trend with low bandwidth) before downgrading (duration)
unstable_duration: "6s"
# how long to wait before upgrading again after previous upgrade (duration)
upgrade_backoff: "5s"