# Transport quality detectors

Delay, loss, congestion and stalled media transport.

Version coverage: /docs/reference/versions/


{{< detector-table >}}
{{< detector-row name="CongestionDetector" description="Legacy congestion detection; deprecated in favor of directional detectors." trigger="deprecated sensitivity medium; legacy RTT/loss/limitation heuristic" recovery="legacy congested flag and max-baseline bookkeeping; not interchangeable with directional detectors" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/CongestionDetector.ts#L77" displayName="Congestion" collects="Legacy RTT, packet loss and bandwidth-limitation measurements." example="Rising RTT and loss contribute to the legacy congestion verdict." >}}
{{< detector-row name="UplinkCongestionDetector" description="Detects congestion on the sending side." trigger="browser bandwidth-limited verdict AND severity≥0.65; severity = sqrt(BWE undershoot × pacer bloat); bloat saturates at 4×median" recovery="closes when browser stops reporting bandwidth limitation or send path stands down; decaying max and median baselines" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/UplinkCongestionDetector.ts#L95" displayName="Uplink Congestion" collects="Browser bandwidth limitation, bandwidth estimates and sender pacing delay." example="The browser reports bandwidth limitation while the send queue grows." >}}
{{< detector-row name="DownlinkCongestionDetector" description="Detects congestion on the receiving side." trigger="inbound video; severity≥0.65 = sqrt(receive-bitrate undershoot × video jitter-buffer bloat), 4×median saturation" recovery="below half `minSeverity` (0.325 default), or no inbound video; separate baselines" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/DownlinkCongestionDetector.ts#L105" displayName="Downlink Congestion" collects="Inbound video bitrate and video jitter-buffer growth." example="Receiving bitrate falls while buffered video delay rises." >}}
{{< detector-row name="TransportDelayDetector" description="Detects sustained high round-trip delay." trigger="detection-window mean current RTT≥300 ms" recovery="recovery-window RTT<200 ms or no measurement; RTCP/ICE source retained" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/TransportDelayDetector.ts#L70" displayName="Transport Delay" collects="Current round-trip time from RTCP or ICE measurements." example="Average RTT stays above 300 ms across the detection window." >}}
{{< detector-row name="TransportLossDetector" description="Detects sustained packet loss." trigger="max available inbound/outbound mean loss≥0.05 for 6000 ms" recovery="loss<0.01; hysteresis between thresholds" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/TransportLossDetector.ts#L47" displayName="Transport Loss" collects="Available inbound and outbound mean packet-loss measurements." example="Packet loss stays at or above five percent for six seconds." >}}
{{< detector-row name="BlockedStunRequestsDetector" description="Detects STUN checks that receive no responses." trigger="succeeded pair sends requests/consent checks but no responses for 10000 ms" recovery="response arrives/path unverified/no request evidence; separate 10000 ms request timeout; issue is blocked-stun-requests, event remains blocked-transport" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/BlockedStunRequestsDetector.ts#L52" displayName="Blocked Stun Requests" collects="STUN request, consent-check and response activity on an established pair." example="Consent requests continue, but no responses arrive during the timeout." >}}
{{< detector-row name="BlockedOutboundMediaDetector" description="Detects outgoing media without fresh receiver reports." trigger="actual outgoing RTP, STUN answers, fresh remote receiver reports stop for 10000 ms" recovery="reports resume, no sending or no usable path; absent RTCP is evidence with the other gates, not proof of a particular firewall" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/BlockedOutboundMediaDetector.ts#L50" displayName="Blocked Outbound Media" collects="Outgoing RTP, STUN responses and freshness of remote receiver reports." example="Media is sent and STUN answers arrive, but fresh receiver reports stop." >}}
{{< detector-row name="BlockedInboundMediaDetector" description="Detects missing incoming media despite sender activity; disabled by default." trigger="**default null**; sender-report evidence advances while inbound media does not, for configured threshold" recovery="reception resumes/no sending or no usable path; enable only where evidence is meaningful" source="https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/BlockedInboundMediaDetector.ts#L58" displayName="Blocked Inbound Media" collects="Sender-report progress and incoming media activity." example="Sender reports advance while no incoming media appears; use only where that evidence is meaningful." >}}
{{< /detector-table >}}

Directional formulas and baseline update order: [client-monitor-js/src/detectors/UplinkCongestionDetector.ts · update](https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/UplinkCongestionDetector.ts#L129), [client-monitor-js/src/detectors/DownlinkCongestionDetector.ts · update](https://github.com/ObserveRTC/client-monitor-js/blob/0f08bd5d110a4e9d53cf0486962e638c5b393c49/src/detectors/DownlinkCongestionDetector.ts#L138). The baseline is read before feeding the current observation; medians stop learning while an issue is open. These are not generic packet-loss thresholds.

