The producer's presentation ticks start at zero per session and sit in its
clock domain; handed to the mixer they read as ever-growing drift, and OBS
kept adding buffering and restarting the source's audio for lagging.
OBS's own network sources stamp with the receive clock; so does this one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The operator ruled that Odin folds back to the port every consumer already
uses rather than moving the estate to a staging port; the default follows.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The OBS source defaulted to the old Odin port; Idunn publishes Odin's
rendezvous at rudp://10.77.0.1:17971 (an nginx stream route in front of the
per-release daemon port). The `catalog` example pulls the same
advertisements the picker does and prints them, for the field question
"why does the plugin show nothing".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
RatatoskrReceiver is a CultNet RUDP client towards the advertisement's
media_endpoint, known to the producer by its receiver id as the connect
payload. It redials every second until answered, pings, and treats 4 s of
silence or an explicit disconnect as a detach that it reports and redials
from. Audio arrives on its own channel. Nothing on the consumer's host
listens, so it needs no firewall rule or port forward.
The request no longer carries a receiver endpoint; the OBS source asks
first, then dials. ratatoskr_receiver_local_port is replaced by
ratatoskr_receiver_attached, and the "This host, as the producer reaches
it" setting is gone. CultLib pin c84cb2e.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A new source type, "CultMesh Media Stream". Its properties pull every
gamecult.media_stream_advertisement Odin holds and offer each stream's
video sources, audio sources and codecs from the advertisement, with
bitrate and latency budget; activating publishes a
gamecult.media_stream_request naming this receiver's endpoint. Nothing
in the picker comes from configuration or from Muninn.
The core grows the mesh half (catalog.rs): pull the advertisements,
publish a request, read the producer's answer, all over cultmesh-rs and
tested against an Odin-shaped RUDP catalog server on loopback. The C ABI
gains the catalog and request calls, a video relay that copies each
whole access unit to a loopback UDP port as a raw byte stream, and the
producer's presentation time on every payload.
The plugin itself owns only the OBS lifecycle. Video is drawn from a
private ffmpeg_source child reading the relay — the arrangement the
previous plugin proved in the field, minus the 2,500 lines of transport
it hand-rolled underneath. Audio is PCM straight to
obs_source_output_audio.
Built against a libobs-only build of obs-studio 32.2.2 with obs-deps
2026-07-15 under .sdk/ (git-ignored; the README says how). Installed to
the per-user OBS plugins directory. Not yet exercised with a live stream.
cargo test -p ratatoskr-core -> 31 passed
abi_smoke.exe ratatoskr_core.dll -> ABI SMOKE PASSED
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>