diff --git a/README.md b/README.md index c0b5acd..c1055c0 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Docker is the easiest way to run it. - [macOS](#macos) - [No Docker (.bat / .sh)](#no-docker-bat--sh) - [Production Package Scripts](#production-package-scripts) +- [WebRTC Streaming](#webrtc-streaming) - [Docker Notes (TLS, reverse proxy, cache)](#docker-notes-tls-reverse-proxy-cache) --- @@ -341,6 +342,66 @@ Output: `release/prod-package/` --- +## WebRTC Streaming + +The remote desktop viewer has a **Transport** dropdown with three modes: + +- **Canvas** (default): H.264 / JPEG / block frames over the existing WebSocket, decoded into a ``. Highest latency, works anywhere the WS does. +- **WebRTC P2P**: browser ↔ agent direct. The server only relays SDP and ICE candidates over the existing WS — MediaMTX is not involved. Lowest latency. Fails when both sides are behind aggressive symmetric NAT. +- **WebRTC Relayed**: agent publishes to a MediaMTX sidecar via WHIP, browser plays via WHEP. The server proxies signaling so the existing JWT auth + per-client RBAC still apply. Lowest-effort fallback when P2P can't punch through. + +### Building agents with WebRTC + +WebRTC is **opt-in per agent build**. In the builder UI, tick the **WebRTC** checkbox before clicking Build. Without it, the Pion stack (~6 MB of Go modules) is not compiled in — any WebRTC start attempt from the operator returns `webrtc support not compiled in` and the viewer falls back to Canvas. The Canvas path always works regardless of the build setting. + +The build tag (`overlord_webrtc`) is also available if you build agents outside the UI: + +```bash +go build -tags overlord_webrtc ./cmd/agent +``` + +### MediaMTX sidecar + +Compose starts an `overlord-mediamtx` service for Relayed mode. It needs: + +- Port `8189/udp` and `8189/tcp` reachable from operators (WebRTC ICE traffic). The Windows / macOS compose publishes these; Linux uses host networking and shares the host's interfaces directly. +- No auth config — the Overlord server proxies every WHIP/WHEP request through `/api/webrtc/...` and enforces the existing operator JWT + RBAC there. + +If you only ever want P2P, you can comment out the `mediamtx:` service in your compose file — only Relayed mode depends on it. + +### LAN / public access + +By default MediaMTX advertises `127.0.0.1` as an ICE candidate, which is enough for operators running their browser on the same machine as Docker. + +For viewers on a different machine: + +- **Linux** (host networking): nothing to configure — MediaMTX sees the host's eth0/wlan0 and gathers those candidates automatically. +- **Windows / macOS** (bridge networking): set `OVERLORD_WEBRTC_ADDITIONAL_HOSTS` to a comma-separated list including the server's reachable LAN or public IP. Either export it in your shell, or add it to a `.env` file next to the compose file: + + ``` + OVERLORD_WEBRTC_ADDITIONAL_HOSTS=127.0.0.1,192.168.1.42 + ``` + + Then `docker compose -f docker-compose.windows.yml up -d mediamtx` to apply. + +### Advanced MediaMTX customization + +The compose file passes a minimal set of `MTX_*` environment variables to MediaMTX — enough for Overlord to work. To change anything else (codecs, paths, ICE servers, etc.), either: + +- Add more `MTX_*` variables to the `mediamtx` service's `environment:` block (every option in MediaMTX's docs is supported as an env var), or +- Provide a full `mediamtx.yml` via a bind mount: + + ```yaml + mediamtx: + # ...existing config... + volumes: + - ./mediamtx.yml:/mediamtx.yml:ro + ``` + + Make sure the file exists on the host *before* the container starts — Docker will otherwise auto-create an empty directory at that path and fail with "not a directory". + +--- + ## Docker Notes (TLS, reverse proxy, cache) Notes on configs and workarounds. diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml index 7b91a26..684cd55 100644 --- a/docker-compose.windows.yml +++ b/docker-compose.windows.yml @@ -43,7 +43,6 @@ services: OVERLORD_FILE_UPLOAD_PULL_TTL_MS: ${OVERLORD_FILE_UPLOAD_PULL_TTL_MS:-1800000} # WebRTC: Bun reaches MediaMTX via the docker service name on bridge net. OVERLORD_MEDIAMTX_URL: ${OVERLORD_MEDIAMTX_URL:-http://mediamtx:8889} - OVERLORD_WEBRTC_PUBLIC_HOST: ${OVERLORD_WEBRTC_PUBLIC_HOST:-} depends_on: - mediamtx volumes: @@ -77,10 +76,21 @@ services: # outside world (browser + agent), so publish 8189. - "8189:8189/udp" - "8189:8189/tcp" - volumes: - - ./mediamtx.yml:/mediamtx.yml:ro environment: - MTX_WEBRTCADDITIONALHOSTS: ${OVERLORD_WEBRTC_PUBLIC_HOST:-} + # Disable every protocol except WebRTC. The Overlord server proxies all + # WHIP/WHEP signaling and enforces auth itself. + MTX_RTSP: "no" + MTX_RTMP: "no" + MTX_HLS: "no" + MTX_SRT: "no" + # Fixed ICE ports (matched by the port-publish above). + MTX_WEBRTCLOCALUDPADDRESS: ":8189" + MTX_WEBRTCLOCALTCPADDRESS: ":8189" + # Advertise 127.0.0.1 as an ICE candidate so browsers on the docker + # host can reach MediaMTX through the published port. For viewers on + # a different machine, override with the host's LAN/public IP, e.g.: + # OVERLORD_WEBRTC_ADDITIONAL_HOSTS=127.0.0.1,192.168.1.42 + MTX_WEBRTCADDITIONALHOSTS: ${OVERLORD_WEBRTC_ADDITIONAL_HOSTS:-127.0.0.1} volumes: overlord-data: diff --git a/docker-compose.yml b/docker-compose.yml index 5705f2a..1fd6aed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,9 +47,6 @@ services: # Host networking on Linux → localhost works. WebRTC is opt-in; leave the # toggle in the UI off if MediaMTX is not running. OVERLORD_MEDIAMTX_URL: ${OVERLORD_MEDIAMTX_URL:-http://localhost:8889} - # Public address advertised to browsers/agents for ICE. Defaults to the - # request host (Bun rewrites the WHEP candidate list when needed). - OVERLORD_WEBRTC_PUBLIC_HOST: ${OVERLORD_WEBRTC_PUBLIC_HOST:-} volumes: # overlord-data also caches downloaded cross-compile toolchains # under /app/data/toolchains, fetched on first agent build for a @@ -77,14 +74,27 @@ services: mediamtx: image: bluenviron/mediamtx:latest container_name: overlord-mediamtx - # Share the host network so WebRTC ICE UDP candidates use the host's - # interfaces directly. Same trade-off as the main service. + # Share the host network so WebRTC ICE candidates use the host's real + # interfaces directly — no extra config needed for local or LAN browsers. network_mode: host restart: unless-stopped - volumes: - - ./mediamtx.yml:/mediamtx.yml:ro environment: - MTX_WEBRTCADDITIONALHOSTS: ${OVERLORD_WEBRTC_PUBLIC_HOST:-} + # Disable every protocol except WebRTC. The Overlord server proxies all + # WHIP/WHEP signaling and enforces auth itself, so MediaMTX doesn't + # need RTSP/RTMP/HLS/SRT listeners. + MTX_RTSP: "no" + MTX_RTMP: "no" + MTX_HLS: "no" + MTX_SRT: "no" + # ICE on fixed ports so the compose / host firewall has a single target. + MTX_WEBRTCLOCALUDPADDRESS: ":8189" + MTX_WEBRTCLOCALTCPADDRESS: ":8189" + # Advertise 127.0.0.1 as an ICE candidate. Always required on Windows / + # macOS (bridge networking); harmless on Linux (host networking). To + # allow viewers on a different machine, override this with a comma- + # separated list including the host's LAN/public IP, e.g.: + # OVERLORD_WEBRTC_ADDITIONAL_HOSTS=127.0.0.1,192.168.1.42 + MTX_WEBRTCADDITIONALHOSTS: ${OVERLORD_WEBRTC_ADDITIONAL_HOSTS:-127.0.0.1} volumes: overlord-data: diff --git a/mediamtx.yml b/mediamtx.yml index ecc9235..3de41e0 100644 --- a/mediamtx.yml +++ b/mediamtx.yml @@ -30,10 +30,19 @@ webrtcAllowOrigins: ['*'] # punch through to MediaMTX directly without TURN. webrtcLocalUDPAddress: :8189 webrtcLocalTCPAddress: :8189 -# Optional: set OVERLORD_WEBRTC_PUBLIC_HOST to your public IP/hostname and -# uncomment to add explicit ICE candidates (needed behind NAT). -# webrtcAdditionalHosts: -# - ${OVERLORD_WEBRTC_PUBLIC_HOST} +# Always advertise the loopback as an ICE candidate. +# +# • Linux (host networking): MediaMTX already sees every real interface, so +# this is only used by browsers running on the server itself. +# • Windows / macOS (bridge networking): the container can only see the +# docker bridge IP, which the host can't reach. Browsers running on the +# docker host connect to 127.0.0.1:8189 instead, which Docker Desktop +# port-publishes into the MediaMTX container. +# +# For LAN access from a different machine, add that machine's LAN IP (or +# the server's reachable public IP) here, e.g.: +# webrtcAdditionalHosts: ['127.0.0.1', '192.168.1.42'] +webrtcAdditionalHosts: ['127.0.0.1'] paths: # Accept any path created by a publisher (WHIP). Overlord uses