- Add cache *keyFrameCache field to Source (nil by default).
- Add EnableKeyFrameCache() — call before Start() on video sources to
activate IDR burst caching.
- readLoop: call cache.push(pkt) after each successful unmarshal, before
the subscriber fanout. No lock held at push time — push acquires its
own mutex internally.
- Subscribe: snapshot the cache outside s.mu to avoid any cross-lock
complexity, then pre-fill the new channel with the burst before
registering it in the subscriber set. Uses a labeled break to stop
pre-filling if the channel is full (bufDepth too small for the burst;
the subscriber will wait for the next live keyframe instead).
- core/webrtc: NewSourceOn(streamID, host, port) allows binding the
RTP UDP socket on something other than 127.0.0.1, required when the
PoC runs in a container and must accept RTP from LAN publishers.
NewSource(streamID, port) stays as a convenience wrapper on
127.0.0.1 for existing tests and tight local tests.
- cmd/webrtc-poc: new -rtp-host flag (default 127.0.0.1 for safety).
- deploy/docker/Dockerfile: two-stage build, scratch runtime, ~14 MB.
- deploy/truenas/docker-compose.yml: host-networked stack template
driven by a .env file. Host networking is required for WebRTC ICE
to work without NAT rewriting per-candidate.
- deploy/truenas/README.md: operator runbook with port picking,
bring-up, verification curls, and security notes.