2026-05-03 08:22:25 -04:00
|
|
|
|
# Datarhei — Dragon Fork
|
2022-08-02 13:10:28 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
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.
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
```
|
|
|
|
|
|
publisher (OBS / FFmpeg / SRT) ──▶ datarhei Core ──▶ WebRTC peers
|
|
|
|
|
|
│ │ (1–5 viewers per stream)
|
|
|
|
|
|
│ ├──▶ HLS / DASH (existing)
|
|
|
|
|
|
│ ├──▶ RTMP relay (existing)
|
|
|
|
|
|
└──▶ ingest (RTMP / SRT / …) └──▶ recording (existing)
|
|
|
|
|
|
```
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
Sub-second glass-to-glass on a LAN over WHEP, no SFU dependencies,
|
|
|
|
|
|
single binary, single Docker image.
|
|
|
|
|
|
|
2026-05-03 16:34:44 -04:00
|
|
|
|
> **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.
|
2026-05-03 08:22:25 -04:00
|
|
|
|
|
|
|
|
|
|
## 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.
|
2026-05-03 16:34:44 -04:00
|
|
|
|
- **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.
|
2026-05-03 08:22:25 -04:00
|
|
|
|
- **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.
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
## Quick start
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
### Docker (TrueNAS / any host with Docker + LAN-reachable IP)
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
```sh
|
|
|
|
|
|
git clone https://forge.wilddragon.net/zgaetano/datarhei-dragonfork-core.git
|
|
|
|
|
|
cd datarhei-dragonfork-core/deploy/truenas/core
|
|
|
|
|
|
|
|
|
|
|
|
cat > .env <<EOF
|
|
|
|
|
|
PUBLIC_IP=10.0.0.25
|
|
|
|
|
|
CORE_HTTP_PORT=8080
|
|
|
|
|
|
API_AUTH_USERNAME=admin
|
|
|
|
|
|
API_AUTH_PASSWORD=$(openssl rand -base64 24)
|
|
|
|
|
|
API_AUTH_JWT_SECRET=$(openssl rand -base64 48)
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
docker compose up -d --build
|
|
|
|
|
|
```
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 16:34:44 -04:00
|
|
|
|
Then open in a browser (replace `<host>` with your `PUBLIC_IP`):
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 16:34:44 -04:00
|
|
|
|
| URL | What it does |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| `http://<host>:8080/` | **Restreamer UI** — manage processes, ingests, outputs |
|
|
|
|
|
|
| `http://<host>:8080/wilddragon-webrtc.html` | **Wild Dragon WebRTC admin** — toggle `webrtc.enabled` per process, copy WHEP URL |
|
|
|
|
|
|
| `http://<host>:8080/whep-player.html` | **WHEP smoke player** — verify the WebRTC stream renders |
|
|
|
|
|
|
| `http://<host>: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.
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
### Sample process JSON
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "live",
|
|
|
|
|
|
"input": [
|
|
|
|
|
|
{ "address": "{rtmp,name=live.stream}", "options": [] }
|
|
|
|
|
|
],
|
|
|
|
|
|
"output": [],
|
|
|
|
|
|
"webrtc": { "enabled": true }
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
## Documentation
|
2023-02-23 04:23:32 -05:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
| 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) |
|
2026-05-03 16:34:44 -04:00
|
|
|
|
| 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) |
|
2026-05-03 08:22:25 -04:00
|
|
|
|
| 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) |
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
## Building from source
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
Go 1.24 required (vendored).
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
|
|
|
|
|
```sh
|
2026-05-03 08:22:25 -04:00
|
|
|
|
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
|
2022-05-13 13:26:45 -04:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
## From upstream Datarhei
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
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.
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
| 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:
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
- **datarhei Core** — Apache 2.0, © datarhei. The base repository this
|
|
|
|
|
|
fork tracks. See [`NOTICE`](NOTICE) for the required attribution.
|
2026-05-03 16:34:44 -04:00
|
|
|
|
- **datarhei Restreamer UI** — Apache 2.0, © datarhei. The React frontend
|
|
|
|
|
|
bundled into the TrueNAS deploy image with Wild Dragon overlays.
|
2026-05-03 08:22:25 -04:00
|
|
|
|
- **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.
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
Full third-party credits in [`CREDITS`](CREDITS).
|
2022-05-13 13:26:45 -04:00
|
|
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
2026-05-03 08:22:25 -04:00
|
|
|
|
Apache License 2.0 — same as upstream. See [`LICENSE`](LICENSE).
|