Summary
First-publisher-wins dedup for RTMP publishes is scoped to a single run() call: ActivePaths is created inside run (rs/moq-rtmp/src/listen.rs:104 on main). The documented way to serve RTMP + RTMPS is to call run twice against a cloned origin, which the bundled binary does. Two publishers hitting the same stream key via the two listeners both pass their local claim, and OriginProducer::publish_broadcast does not reject duplicates; it queues the loser as a backup and promotes it later.
Impact
A second OBS instance "successfully" streams into an invisible backup slot, then gets promoted mid-stream with a timestamp discontinuity when the first publisher drops. This contradicts the adjacent comment claiming duplicate publishes are rejected.
Suggested fix
Share ActivePaths across listeners (e.g. create it in Config or key it off the origin), or make the claim collision-checked at the origin level.
Found during a full review of the dev branch; verified on main.
(Written by Claude Fable 5)
Summary
First-publisher-wins dedup for RTMP publishes is scoped to a single
run()call:ActivePathsis created insiderun(rs/moq-rtmp/src/listen.rs:104on main). The documented way to serve RTMP + RTMPS is to callruntwice against a cloned origin, which the bundled binary does. Two publishers hitting the same stream key via the two listeners both pass their local claim, andOriginProducer::publish_broadcastdoes not reject duplicates; it queues the loser as a backup and promotes it later.Impact
A second OBS instance "successfully" streams into an invisible backup slot, then gets promoted mid-stream with a timestamp discontinuity when the first publisher drops. This contradicts the adjacent comment claiming duplicate publishes are rejected.
Suggested fix
Share
ActivePathsacross listeners (e.g. create it inConfigor key it off the origin), or make the claim collision-checked at the origin level.Found during a full review of the dev branch; verified on main.
(Written by Claude Fable 5)