datarhei-dragonfork-core/README.md
ZGaetano 9e9c7eb8f1
Some checks failed
ci / race tests (push) Blocked by required conditions
ci / WebRTC smoke (5-viewer fanout) (push) Blocked by required conditions
ci / WebRTC latency p95 gate (push) Blocked by required conditions
ci / vet + build (push) Has been cancelled
docs: update README quick-start with Prometheus/Grafana and Docker publish
2026-05-06 16:04:02 -04:00

203 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
│ │ (15 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 in progress (last work 2026-05-06). Full GUI bundled
> (Restreamer UI + Wild Dragon WebRTC admin). Prometheus + Grafana
> observability stack shipped. 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.
- **Prometheus observability** — eleven `dragonfork_webrtc_*` metrics
(RED-method counters/histograms + state gauges). Grafana health
dashboard with 5 rows and 4 pre-loaded alert rules.
- **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 <<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)
GRAFANA_ADMIN_PASSWORD=$(openssl rand -base64 24)
GRAFANA_PORT=3000
PROM_PORT=9090
EOF
docker compose up -d --build
```
Then open in a browser (replace `<host>` with your `PUBLIC_IP`):
| 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>:3000/` | **Grafana** — WebRTC Health dashboard (login with `GRAFANA_ADMIN_PASSWORD`) |
| `http://<host>:9090/` | **Prometheus** — raw metrics, alert rules |
| `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.
### Pulling a pre-built image (after first tag is published)
```sh
# Update .env, then:
docker compose pull # pulls pre-built multi-arch image
docker compose up -d # no --build needed
```
### 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 | [`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) |
| Upstream rebase policy | [`docs/REBASE.md`](docs/REBASE.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
```
## Load testing
```sh
go run ./test/load/sustained.go \
-url http://<host>:8080 \
-stream <processID> \
-peers 5 \
-duration 10m \
-auth "Bearer <TOKEN>" \
-out test/load/results/
```
Reports are written to `test/load/results/`. Observe the Grafana
WebRTC Health dashboard during the run.
## 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).