While analyzing a year of mediamtx logs to get stats on livestream usage, I found two issues in the player code.
1. The WebRTC reader is recreated every time isStreamingTimeout changes
In useMediaMtx.tsx, the reader is built in a useMemo that has isStreamingTimeout in its dependencies. That flag flips to true after 30s without action (LIVE_STREAMING_TIMEOUT_SECONDS) and back to false on every camera action, so each flip recreates the reader: the cleanup effect closes the current WebRTC session and immediately opens a new one, while the video is playing fine.
The logs confirm it: 3,074 view sessions (about a third of the total) start less than 3s after the previous one closed on the same path, and the median duration of the session preceding such a reconnection is 31s, which matches the 30s timeout exactly. In practice a user passively watching for 90s generates 3 WebRTC sessions on a single publish.
isStreamingTimeout is only used inside the onError callback to pick between FAILED and TEMPORARY_ERROR, so it could be read through a ref instead of being a memo dependency.
2. No backoff on the WHEP retry loop
reader.js retries every 1s (fixed, up to 20 times) while waiting for the engine to start publishing. Over a year this produced about 258,000 WebRTC sessions closed with "no stream is available", vs 8,964 actual views. An exponential backoff (1s, 2s, 4s...) would cut this noise by an order of magnitude without hurting perceived startup time.
While analyzing a year of mediamtx logs to get stats on livestream usage, I found two issues in the player code.
1. The WebRTC reader is recreated every time
isStreamingTimeoutchangesIn
useMediaMtx.tsx, the reader is built in auseMemothat hasisStreamingTimeoutin its dependencies. That flag flips totrueafter 30s without action (LIVE_STREAMING_TIMEOUT_SECONDS) and back tofalseon every camera action, so each flip recreates the reader: the cleanup effect closes the current WebRTC session and immediately opens a new one, while the video is playing fine.The logs confirm it: 3,074 view sessions (about a third of the total) start less than 3s after the previous one closed on the same path, and the median duration of the session preceding such a reconnection is 31s, which matches the 30s timeout exactly. In practice a user passively watching for 90s generates 3 WebRTC sessions on a single publish.
isStreamingTimeoutis only used inside theonErrorcallback to pick betweenFAILEDandTEMPORARY_ERROR, so it could be read through a ref instead of being a memo dependency.2. No backoff on the WHEP retry loop
reader.jsretries every 1s (fixed, up to 20 times) while waiting for the engine to start publishing. Over a year this produced about 258,000 WebRTC sessions closed with "no stream is available", vs 8,964 actual views. An exponential backoff (1s, 2s, 4s...) would cut this noise by an order of magnitude without hurting perceived startup time.