Menu Home
ProductReplay & DevToolsSignalsCall qualityWhy (AI)Live AssistCanvas recordingPrivacy & complianceSelf-hosted
SolutionsHealthcare & virtual careEngineeringSupportProduct teamsKiosks & monitoring
MorePricingDocsCompareTrust centerGlossaryAboutContactPress kit
Log inStart free
Call quality

The call failed. Now you can prove why.

The replay is only half the story. Backstory records WebRTC state and quality next to the page, so a frozen video and the click that followed it sit on one timeline.

Signals 0 fired

    Why generated from this session

    Loading explanation…

    WebRTC quality events sit on the same timeline as everything else, so the moment a call degraded is the moment you can scrub to.

    What it catches

    Start with the failures nobody can diagnose today.

    Every replay tool can show you a user clicking. None of them can tell you the far end never sent audio.

    One-way audio

    “They could not hear me.”

    Packets leave one side and never arrive at the other, while both ends believe the call is up. We see outbound packets climbing against a receiver that reports nothing, and name it. Today this is a twenty-minute phone call that ends in a shrug.

    Device in use

    “My camera does not work.”

    Another application is holding the camera, so the browser rejects the request with NotReadableError. The user sees a black rectangle and blames your app. We record the exact rejection class before any video was ever negotiated.

    Relay fallback

    “It only breaks on their network.”

    The network blocked peer-to-peer, so media went through a TURN relay and picked up latency on the way. The candidate types prove it. One relayed call is normal; relayed calls concentrated in one site or one release is a finding.

    CPU limited

    “The video looked terrible.”

    The encoder could not keep up, so it dropped resolution. Not the network: the device. On a shared workstation or a wall-mounted kiosk this is the usual answer, and it points at hardware rather than bandwidth.

    Media frames are never captured.

    We record metrics and state. The call's audio and video never leave the device, in any configuration. That is what makes call observability safe to switch on in a HIPAA environment, where the media itself is protected health information. ICE candidate addresses are hashed, device labels are masked, and session descriptions are off by default.

    How it works

    Two data paths, two different costs.

    1. Patch RTCPeerConnection, mediaDevices
    2. Events state, tracks, device errors
    3. Sample getStats at 1 Hz → deltas
    4. Detect 13 rules, clustered
    5. Explain one timeline with the DOM
    Lifecycle events are rare and never thinned, so a call that fails to connect is recorded even when the recorder is under pressure. Quality metrics are sampled on the same ladder as pointer moves: every five seconds normally, less often under load, and immediately whenever a threshold is crossed.

    No app changes

    The SDK wraps the browser APIs your call already uses. Nothing to instrument, no SDK of ours inside your call logic. Apps that build a peer connection before we load get an attach() escape hatch.

    Cheap on the wire

    A quality sample is a few hundred bytes, so a call costs a handful of kilobytes per minute. Next to the DOM stream it does not register.

    Web and mobile

    The same metric shape and the same detectors on the browser, iOS, and Android. Vendor SDKs that hide the peer connection can hand us their own statistics instead.

    Metrics

    Answers, not raw stat dumps.

    The SDK differences getStats() reports on the device and sends conclusions. What arrives is already the number you would have computed.

    Quality metrics captured per track and direction
    MetricDerived fromWhat it proves
    Packet losspacketsLost against packets received, or the remote report for outboundThe strongest single predictor of a call people complain about
    Round trip timecurrentRoundTripTime on the selected candidate pairConversational latency. Past 300 ms, people start talking over each other
    Jitter and buffer delayjitter, and jitterBufferDelay over its emitted countNetwork instability, and the buffering half of perceived lag
    FreezesfreezeCount and totalFreezesDuration, with a derived fallback where the browser lacks themThe video freezing: what a user means by “choppy”
    Audio concealmentconcealedSamples over totalSamplesReceivedDropouts. The decoder inventing samples to cover gaps. Past roughly 5% it is audible
    Frame rate and resolutionframesPerSecond, frameWidth, frameHeightQuality collapse under bandwidth or CPU pressure
    Quality limitation reasonqualityLimitationReason and its durationsWhether the network or the device was the constraint
    Available bitrateThe congestion controller's own estimateHow much headroom was left before it degraded
    Candidate typesThe selected pair joined to the candidate statsDirect or relayed, over UDP or TCP, on wifi or cellular
    Audio levelThe receiver level, or the local media sourceSilence while unmuted: half of the one-way audio diagnosis
    Detectors

    Thirteen rules that run on every call.

    Deterministic, tunable per project, and clustered across sessions the same way every other Signal is.

    WebRTC detectors and their default thresholds
    DetectorRule (defaults)Severity
    Connect failureNever reached connected within 15 s, or reached failedCritical
    One-way mediaOne direction moved zero packets for 6 s while the other flowedCritical
    Media permission deniedgetUserMedia rejected with NotAllowedErrorHigh
    Device unavailableRejected with NotReadableError or NotFoundErrorHigh
    FreezeA single freeze over 2 s, or more than 5% of the call frozenHigh
    Audio dropoutConcealment above 5% sustained for 10 sHigh
    Reconnect stormThree or more ICE restarts or path changes within 60 sHigh
    Call abandonedEnded inside 30 s with a quality score below 60High
    Packet lossAbove 5% sustained for 10 sMedium
    High latencyRound trip time above 300 ms sustained for 15 sMedium
    CPU limitedEncoder CPU-limited for more than 20% of the callMedium
    Low resolutionBelow 240 px high for 20 s after a better resolution was seenLow
    Relay fallbackThe selected path is a TURN relayInfo

    Each call also gets a composite quality score from 0 to 100, weighted toward loss and freezes. The score the detector fires on and the score a support agent reads are computed by the same function, so they cannot disagree.

    The whole narrative

    A quality graph cannot tell you the user gave up.

    A dedicated WebRTC dashboard will tell you the jitter buffer reached 400 ms. It cannot tell you the user clicked Start, waited eight seconds, saw nothing, clicked Refresh three times, and got a 500 back from your session endpoint. A replay tool can show you all of that and has no idea the media path had failed over to a relay.

    Putting both on one timeline is the point. The Media panel sits beside Console and Network in the Player, with metric lanes aligned to the scrubber and a marker for every state change. Because no frames were recorded, a frozen video element is labelled with the freeze and its duration, which is the more useful artifact anyway. Ask Why weighs the call and the page together, so the explanation names both halves of the failure and cites the moment of each.

    Media panel

    Per connection: state at the playhead, direct or relayed, codec, and the running score. Lanes for latency, loss, jitter, frame rate, bitrate, and audio level. Freeze bands. Clickable markers.

    Calls view

    Every call, with quality score, setup time, relay status, network type, and the issues found. Filter to the bad ones, then jump into the replay at the moment it went wrong.

    Cohorts

    Connect failure rate and relay rate broken down by network type, browser, device, and release. The question “is it us or their network” becomes answerable.

    Long calls

    A twelve-hour shift, and the four minutes that mattered.

    A WebRTC call can run for a full shift. Recording all of it would be expensive and almost entirely uninteresting. Every call detector doubles as a monitor-mode trigger, so a lost feed, a freeze, or a reconnect flushes the sixty-second pre-roll and records a full-fidelity burst around the problem.

    What a supervisor reviews the next morning is a handful of bursts with the minute before each one intact, not twelve hours of a stable video wall. See kiosks and monitoring for how monitor mode works.

    Your media server too

    Client-side tells you what they saw. The server tells you who was at fault.

    Client statistics describe one participant's experience. Joining them to the media server's view separates a bad uplink from a bad downlink. Where a customer runs their own media server, the participant identity is the join key and the two land on the same call record; the same pattern applies to any hosted service that reports per-participant statistics. Call quality is also exported as OpenTelemetry metrics, so an existing observability stack can consume it without integrating with us at all.

    The story behind every bug.

    Free for 1,000 sessions a month. Strict masking, conditional recording, and Signals are all included.

    Get started

    Replay your first session in five minutes.

    Free for 1,000 sessions a month, no credit card. Or leave a work email and we will reach out about the private beta for healthcare and support teams.