diff --git a/CHANGELOG.md b/CHANGELOG.md index 4702f1d..e927915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,94 @@ # Datarhei — Dragon Fork +## v0.3.0-dragonfork (2026-05-10) + +WebRTC ingest (WHIP) milestone. Browsers and OBS can now push a +WebRTC stream into a channel, and the first-frame experience for WHEP +viewers is dramatically improved by the in-memory keyframe cache. + +Resolves issues #15, #16, #17. + +### Added + +- **WHIP ingest path** — browsers and OBS Studio can push a WebRTC + stream (H.264 + Opus) into any Dragon Fork channel via + `POST /api/v3/whip/{id}`. The publisher sends an SDP offer; Core + answers, allocates a loopback UDP pair, and injects RTP input legs + into the FFmpeg command line — the exact mirror of the WHEP egress + path. `DELETE /api/v3/whip/{id}/{resource}` tears down the publisher + cleanly. Closes #16. + +- **`ProcessConfigWHIPIngest` API struct** in `http/api/process.go` + mapping `whip_ingest.{enabled,video_pt,audio_pt}` between the JSON + API and `app.ConfigWHIPIngest`. Without this struct, `WHIPIngest.Enabled` + was always false and WHIP could never activate via the API. + +- **WHIP ingest lifecycle hooks** — `onWHIPProcessStart` / + `onWHIPProcessStop` in `app/webrtc/whip_lifecycle.go` allocate and + teardown the ingest UDP port pair, controlled by the per-process + `whip_ingest.enabled` flag. Merged via `MergedHooks()` alongside the + existing WHEP egress hooks. + +- **Wild Dragon UI — WHIP toggle control** (`overlay/src/misc/controls/WHIP.js` + in the `wilddragon-restreamer-ui` overlay). Mirrors WHEP.js exactly. + Renders an Enable checkbox with caption in the channel edit view. + +- **Wild Dragon UI — Edit/index.js wiring** — renders the WHIP control + in the Edit view and patches `props.restreamer._upsertProcess` in the + `save()` handler to inject `whip_ingest.enabled` into the process + config before the SDK PUT reaches Core. The patch is required because + the Restreamer SDK's `UpsertIngest` does not forward `webrtc` or + `whip_ingest` fields (SDK gap). + +- **In-memory H.264 keyframe cache** in `core/webrtc/keyframecache.go`. + Retains the most recent IDR burst (all RTP packets from the first IDR + NAL fragment until the next one) per video Source. Bounded at 512 + packets / 2 MiB. Detects single-NAL IDR (type 5) and FU-A start + fragments (type 28, start bit set, inner type 5). Closes #17. + +- **Subscribe pre-fill** — `Source.Subscribe()` snapshots the keyframe + cache before registering the new subscriber, then drains the burst + into the channel immediately. New WHEP peers receive a complete + reference frame on join instead of waiting up to one GOP (≈ 2 s at + 30 fps / GOP=60). + +- **`Source.EnableKeyFrameCache()`** — opt-in method; called only on + video sources in `allocAdjacentPair()`. Audio sources are + intentionally uncached (Opus payloads would accumulate without ever + triggering a reset). + +- **Test suite for `core/webrtc`** — `keyframecache_test.go` (18 + functions) and `source_test.go` (5 functions). Covers IDR detection + in all packetisation modes, cache reset, burst accumulation, capacity + caps, snapshot independence, concurrent read/write under `-race`, and + Subscribe pre-fill behaviour. All 34 tests in `core/webrtc` green + under `go test -race`. + +### Fixed + +- **`deploy/truenas/core/seed-data.sh`** — the old no-clobber-only + approach kept stale JS bundles alive on the data volume after image + rebuilds (`static/` was never refreshed because it already existed). + Fixed by splitting into two phases: always-overwrite for `index.html`, + `asset-manifest.json`, and `static/`; no-clobber for everything else + (channel data, player bundles, operator content). Prevents a class of + "new code never runs" deployment bugs. + +### Upgrade (from v0.2) + +```sh +cd deploy/truenas/core +git pull +docker compose build --no-cache core +docker compose up -d core +``` + +The `seed-data.sh` fix means there is no longer a need to manually +`docker exec` a static-bundle copy after rebuilds — it happens +automatically on container start. + +--- + ## v0.2 backlog (2026-05-06) Completes the open v0.2 issues from the post-GUI-ship backlog.