# Datarhei — Dragon Fork A fork of [datarhei/core](https://github.com/datarhei/core) that adds a native **WebRTC (WHEP) egress** path. Everything upstream Datarhei already does — RTMP / SRT / RTSP ingest, FFmpeg process orchestration, HLS / DASH outputs, S3 mounts, the HTTP API and Swagger UI — works unchanged. WebRTC sits alongside as another output type, opt-in per process. ``` publisher (OBS / FFmpeg / SRT) ──▶ datarhei Core ──▶ WebRTC peers │ │ (1–5 viewers per stream) │ ├──▶ HLS / DASH (existing) │ ├──▶ RTMP relay (existing) └──▶ ingest (RTMP / SRT / …) └──▶ recording (existing) ``` Sub-second glass-to-glass on a LAN over WHEP, no SFU dependencies, single binary, single Docker image. > **Status:** v0.2.0-dragonfork shipped 2026-05-03. Full GUI bundled > (Restreamer UI + Wild Dragon WebRTC admin). Live deploy running on > TrueNAS since 2026-04-17. ## What this fork adds - **`webrtc.*` config block** alongside `rtmp.*` and `srt.*`, with the same `CORE_*` env-var binding pattern. - **Per-process `webrtc.enabled` toggle** on the existing process config. Once true, Core auto-injects two RTP output legs (video + audio), allocates UDP ports, and the WHEP endpoint is live. - **`POST /api/v3/whep/{processID}`** — WebRTC-HTTP Egress Protocol subscribe; SDP offer in, SDP answer out. JWT-protected by the existing Core auth. - **`DELETE /api/v3/whep/{processID}/{resourceID}`** — idempotent teardown. - **`PATCH …/{resourceID}`** — trickle ICE. - **Bundled GUI** — the upstream Restreamer React UI is built into the TrueNAS deploy image with Wild Dragon branding, plus a single-file Wild Dragon WebRTC admin page for one-click `webrtc.enabled` toggling. - **Browser-side smoke player** at `whep-player.html` — zero-dependency WHEP subscriber, ICE/codec/bitrate stats, JWT field, shareable `?url=&token=` URLs. - **Multi-viewer correctness:** per-stream peer cap, ICE-failure auto-cleanup, process-stop broadcast tear-down. - **Error matrix** per the design spec: `406` on codec mismatch, `504` on ICE timeout, `503` on cap, `204` on idempotent DELETE, CORS preflights on every WHEP route. The existing upstream Datarhei feature set is intact — see "From upstream Datarhei" below. ## Quick start ### Docker (TrueNAS / any host with Docker + LAN-reachable IP) ```sh git clone https://forge.wilddragon.net/zgaetano/datarhei-dragonfork-core.git cd datarhei-dragonfork-core/deploy/truenas/core cat > .env <` with your `PUBLIC_IP`): | URL | What it does | | --- | --- | | `http://:8080/` | **Restreamer UI** — manage processes, ingests, outputs | | `http://:8080/wilddragon-webrtc.html` | **Wild Dragon WebRTC admin** — toggle `webrtc.enabled` per process, copy WHEP URL | | `http://:8080/whep-player.html` | **WHEP smoke player** — verify the WebRTC stream renders | | `http://:8080/api/swagger/index.html` | **Swagger** — full API docs | The Restreamer UI doesn't yet have a WebRTC checkbox in its process editor — use `/wilddragon-webrtc.html` for that. Tracked in issue #15. ### Sample process JSON ```json { "id": "live", "input": [ { "address": "{rtmp,name=live.stream}", "options": [] } ], "output": [], "webrtc": { "enabled": true } } ``` That's it. No `webrtc://` URL scheme to learn — the toggle on `config.webrtc.enabled` is the entire surface. The resolver allocates ports, injects `-f rtp udp://…` legs into the FFmpeg command, and the WHEP endpoint at `/api/v3/whep/live` becomes live the moment the process starts. For multi-input pipelines (lavfi test sources, multi-camera switches, SDI + file audio), use the `video_map` and `audio_map` fields: ```json "webrtc": { "enabled": true, "video_map": "0:v:0", "audio_map": "1:a:0", "force_transcode": true } ``` ## Documentation | Topic | Where | | ----- | ----- | | Design spec | [`docs/design/2026-04-16-datarhei-dragon-fork-webrtc-design.md`](docs/design/2026-04-16-datarhei-dragon-fork-webrtc-design.md) | | M1 (PoC) plan | [`docs/design/2026-04-16-datarhei-dragon-fork-m1-webrtc-poc.md`](docs/design/2026-04-16-datarhei-dragon-fork-m1-webrtc-poc.md) | | M2 (Core integration) spec | [`docs/design/2026-04-17-datarhei-dragon-fork-m2-webrtc-core-integration.md`](docs/design/2026-04-17-datarhei-dragon-fork-m2-webrtc-core-integration.md) | | Prometheus metrics design (deferred) | [`docs/design/2026-05-03-datarhei-dragon-fork-webrtc-prometheus-metrics-design.md`](docs/design/2026-05-03-datarhei-dragon-fork-webrtc-prometheus-metrics-design.md) | | TrueNAS deploy guide | [`deploy/truenas/core/README.md`](deploy/truenas/core/README.md) | | Testing | [`test/TESTING.md`](test/TESTING.md) | | Changelog (Dragon Fork) | [`CHANGELOG.md`](CHANGELOG.md) | | Upstream Datarhei docs | [docs.datarhei.com/core](https://docs.datarhei.com/core) | ## Building from source Go 1.24 required (vendored). ```sh make release # cross-compiles linux/amd64 to ./core/core make test # full suite, race detector go test -tags latency -timeout 90s -count=1 \ -run TestLatencyServerHop ./app/webrtc/... # latency p95 gate ``` ## From upstream Datarhei This fork preserves everything upstream Datarhei Core does — Dragon Fork is purely additive. If a feature isn't WebRTC-related, the behaviour is unchanged from upstream and the upstream documentation applies as-is. | Subsystem | Upstream feature set | | --- | --- | | Process management | API-driven FFmpeg, error detection / recovery, log history, resource limits, statistics, FFprobe input verification, process metadata | | Media delivery | HTTP/S, RTMP/S, SRT services with Let's Encrypt, configurable file systems (in-memory / disk / S3), HLS/DASH session limits, viewer session API | | Misc | HTTP REST + GraphQL, Swagger, Prometheus metrics, multi-arch Docker images | ## Attribution Dragon Fork is built on: - **datarhei Core** — Apache 2.0, © datarhei. The base repository this fork tracks. See [`NOTICE`](NOTICE) for the required attribution. - **datarhei Restreamer UI** — Apache 2.0, © datarhei. The React frontend bundled into the TrueNAS deploy image with Wild Dragon overlays. - **Pion WebRTC** — MIT. The Go WebRTC stack the egress path is built on. - **FFmpeg** — LGPL / GPL (build-flag dependent). Used as a subprocess for transcoding and RTP packetisation; Dragon Fork doesn't link against it. Full third-party credits in [`CREDITS`](CREDITS). ## License Apache License 2.0 — same as upstream. See [`LICENSE`](LICENSE).