WebRTC Server - Monibuca WHIP/WHEP Low-Latency
WebRTC is the standard technology for ultra-low latency audio/video communication in browsers. Monibuca V6 implements publishing and subscribing based on the WHIP (WebRTC-HTTP Ingestion Protocol) and WHEP (WebRTC-HTTP Egress Protocol) standards, powered by the rustrtc engine for full ICE/DTLS/SRTP support.
Basic Information
Section titled “Basic Information”| Property | Value |
|---|---|
| Signaling Transport | HTTP (WHIP/WHEP) |
| Media Transport | UDP / optional TCP ICE (ICE/DTLS/SRTP) |
| Publish | ✅ Supported (WHIP) |
| Subscribe | ✅ Supported (WHEP) |
| Latency | < 500ms |
| Config section | webrtc |
Configuration
Section titled “Configuration”Enable plugin
Section titled “Enable plugin”The plugin is included in official binaries; configure it in config.yaml:
Configuration File
Section titled “Configuration File”webrtc: enable: true # UDP only (default). Dual ICE: "udp:9000-9100,tcp:9101-9200" port_range: "udp:9000-9100" pli_interval: 2 nack_buffer_size: 200 prefer_srflx_over_natted_host: false public_ip: "" enable_cors: true cors_origins: - "*" ice_servers: - urls: - "stun:stun.l.google.com:19302"| Option | Type | Default | Description |
|---|---|---|---|
enable | bool | true | Whether to enable the WebRTC plugin |
port_range | string | "udp:9000-9100" | ICE media ports: udp:A-B, tcp:A-B, or dual udp:A-B,tcp:C-D (default UDP-only) |
pli_interval | u64 | 2 | PLI (keyframe request) interval (seconds) |
nack_buffer_size | usize | 200 | NACK retransmit history size; RFC 4588 RTX used when browser offers apt= (rustrtc ≥0.3.92) |
prefer_srflx_over_natted_host | bool | false | Prefer srflx over private host in ICE check order |
public_ip | string | "" | Public IP rewritten into host candidates |
enable_cors | bool | true | Whether to enable CORS |
cors_origins | Vec | ["*"] | Allowed cross-origin sources |
ice_servers | Vec | [] | STUN/TURN list |
Dual ICE (UDP + TCP)
Section titled “Dual ICE (UDP + TCP)”When UDP is blocked, gather both UDP host and TCP passive candidates (opt-in):
webrtc: port_range: "udp:9000-9100,tcp:9101-9200" public_ip: "203.0.113.10"Open 9000-9100/udp and 9101-9200/tcp on the firewall. TCP-only: port_range: "tcp:9101-9200".
ICE / TURN servers
Section titled “ICE / TURN servers”ice_servers: - urls: - "stun:stun.l.google.com:19302" - urls: - "turn:turn.example.com:3478?transport=udp" - "turn:turn.example.com:3478?transport=tcp" username: "user" credential: "pass"Minimal coturn sidecar (not embedded in Monibuca):
services: coturn: image: coturn/coturn:latest network_mode: host command: - "-n" - "--log-file=stdout" - "--listening-port=3478" - "--fingerprint" - "--lt-cred-mech" - "--user=user:pass" - "--realm=example.com"Configure the same iceServers on the browser WHIP/WHEP client.
Full Compose reference stack (origin + coturn): repo deploy/compose/.
Codec Support
Section titled “Codec Support”| Type | Codec | Description |
|---|---|---|
| Video | H.264 | Widely supported |
| Video | H.265 | Supported by some browsers |
| Audio | Opus | WebRTC standard audio codec |
WHIP Publishing
Section titled “WHIP Publishing”API Endpoint
Section titled “API Endpoint”POST /webrtc/whip/{streamPath}Content-Type: application/sdpThe request body is an SDP Offer, and the response returns an SDP Answer.
Publishing with FFmpeg
Section titled “Publishing with FFmpeg”FFmpeg 6.1+ supports WHIP publishing:
ffmpeg -re -i input.mp4 \ -c:v libx264 -preset ultrafast -tune zerolatency \ -c:a libopus \ -f whip "http://localhost:8080/webrtc/whip/live/test"Publishing with OBS
Section titled “Publishing with OBS”OBS 30+ has built-in WHIP support:
- Go to Settings → Stream
- Select WHIP for the service
- Enter the server URL:
http://your-server:8080/webrtc/whip/live/test - Click Start Streaming
WHEP Subscribing
Section titled “WHEP Subscribing”API Endpoint
Section titled “API Endpoint”POST /webrtc/whep/{streamPath}Content-Type: application/sdpThe request body is an SDP Offer, and the response returns an SDP Answer.
Browser Subscribing Example
Section titled “Browser Subscribing Example”async function play(streamPath) { const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
pc.addTransceiver('video', { direction: 'recvonly' }); pc.addTransceiver('audio', { direction: 'recvonly' });
pc.ontrack = (event) => { document.getElementById('player').srcObject = event.streams[0]; };
const offer = await pc.createOffer(); await pc.setLocalDescription(offer);
const response = await fetch(`/webrtc/whep/${streamPath}`, { method: 'POST', headers: { 'Content-Type': 'application/sdp' }, body: offer.sdp, });
const answer = await response.text(); await pc.setRemoteDescription({ type: 'answer', sdp: answer });}
play('live/test');Built-in Test Pages
Section titled “Built-in Test Pages”Monibuca provides built-in WebRTC test pages for quick feature verification:
| Page | URL | Description |
|---|---|---|
| Publish Test | /webrtc/test/publish | Publish using camera/screen |
| Subscribe Test | /webrtc/test/subscribe | Play an existing WebRTC stream |
Simply access the URLs in your browser to use them.
NAT Traversal
Section titled “NAT Traversal”In network environments with NAT, proper configuration is required to ensure WebRTC connectivity:
Option 1: Configure Public IP
Section titled “Option 1: Configure Public IP”webrtc: public_ip: "203.0.113.1" # Server's public IPOption 2: Configure STUN/TURN Servers
Section titled “Option 2: Configure STUN/TURN Servers”webrtc: ice_servers: - urls: - "stun:stun.l.google.com:19302" - urls: - "turn:turn.example.com:3478" username: "user" credential: "pass"Option 3: Port Mapping
Section titled “Option 3: Port Mapping”Ensure the UDP port range configured in port_range is open in your firewall:
# Open UDP port rangesudo ufw allow 9000:9100/udpCross-Protocol Forwarding
Section titled “Cross-Protocol Forwarding”After publishing via WebRTC, you can subscribe through other protocols:
# After WebRTC WHIP publishing...
# Subscribe via RTMP (Opus automatically transcoded to AAC)ffplay rtmp://localhost:1935/live/test
# Subscribe via HTTP-FLVffplay http://localhost:8080/flv/live/test.flv
# Subscribe via HLSffplay http://localhost:8080/hls/live/test/index.m3u8