The Problem with webrtc-internals Dumps

When a WebRTC call goes bad, Chrome already recorded everything at chrome://webrtc-internals. You can export a JSON dump, but it's dense, undocumented, and easy to misread. This field guide walks through each section, what to look at first, and the failure signatures that tell you where the call broke.

The Shape of a Dump

A dump has two top-level parts:

  • getUserMedia calls: Every microphone and camera request with constraints and resolved tracks.
  • RTCPeerConnection blocks: Each has connection config (ICE servers), an event log (signaling and ICE state changes), and stats graphs (every getStats() metric sampled over the call).

Read them in that order. Most people jump straight to the graphs and miss that the call never negotiated.

1. The getUserMedia Section: Did You Get the Media You Asked For?

Each entry shows requested constraints and the resolved track. Two quick checks:

  • Asked for video, got audio only? A constraint failed or permission denied. The rest of the call will look "broken" but the root cause is here.
  • Resolution or frame rate lower than requested? The device could not satisfy the constraint and the browser silently downgraded. Worth knowing before you blame the network.

Also note the device brand (microphone and webcam)—it sometimes sheds light on your problem.

2. The Connection Config: Is There a TURN Server?

In the peer connection block, look at the iceServers config. If there is no turn: entry, the call can only connect when both sides have a direct path. On real networks (corporate firewalls, symmetric NAT, mobile), that fails a meaningful fraction of the time. A missing or misconfigured TURN server is one of the most common production failures, and it's invisible unless you look here.

3. The Event Log: How Far Did Negotiation Get?

The event log is the timeline. Read it top to bottom and watch two state machines:

  • Signaling: setLocalDescription and setRemoteDescription firing in order, ending in stable. If you never reach stable, the offer/answer exchange broke (often an SDP or m-line mismatch). No media will flow.
  • ICE connection state: The sequence you want is newcheckingconnectedcompleted. Failure signatures:
    • Stuck in checking, then failed: connectivity. The two sides could not find a working path. Go to candidate pairs.
    • connected then disconnected then back: an unstable network mid-call, not a setup problem.
    • completed cleanly: negotiation is fine. Your problem is media quality. Skip to section 5, but first check the active candidate pair.

4. The Selected Candidate Pair: How Did the Call Connect (or Not)?

Filter the stats for candidate-pair and find the nominated/selected pair. The local and remote candidate types tell a story:

  • host to host: direct local network. Best case.
  • srflx (server-reflexive): connected through NAT via STUN. Normal.
  • relay: the call is going through your TURN server. It works, but costs bandwidth and adds latency. If most calls are relay, that's a finding.
  • No selected pair: ICE failed. Cross-reference the config: if there were no relay candidates and the network needed one, that's your answer.

On the selected pair, currentRoundTripTime is your real network latency. Anything consistently above ~300ms will be felt as lag.

5. The RTP Stats: Where the Quality Actually Lives

This is the part most people mean when they say "read the dump." Look at inbound-rtp (media you received) and outbound-rtp (media you sent), per track. The metrics that matter:

  • packetsLost / packet loss rate: Rising loss on inbound means the network dropped data on the way to you. A few percent is survivable; sustained double digits is not.
  • jitter: Variation in packet arrival timing. High jitter forces the jitter buffer to grow, causing delay or robotic audio.
  • framesPerSecond, frameWidth/frameHeight: If these drop mid-call, the video encoder is shedding quality. The next metric tells you what.
  • qualityLimitationReason (on outbound video): The single most useful field. bandwidth means the network could not carry the bitrate. cpu means the machine could not encode fast enough. none means the encoder was unconstrained.
  • freezeCount / totalFreezesDuration (inbound video): Directly counts visible freezes. If this climbs, the user saw the call stutter.
  • nackCount, pliCount, firCount: Retransmission and keyframe requests. Spikes track loss and decode trouble.
  • Audio: concealmentEvents, insertedSamplesForDeceleration—the audio equivalent of freezes. Rising concealment means the network is hiding gaps, heard as choppy audio.

6. The Graphs: Read the Shape Over Time

Every metric above is plotted over the call. The shape is the diagnosis:

  • Bitrate climbs then collapses, with qualityLimitationReason: bandwidth: Congestion. The call ran out of network and BWE backed off.
  • Packet loss spikes at intervals while RTT stays flat: Bursty loss (Wi-Fi interference, saturated uplink), not pure congestion.
  • Resolution stair-stepping down while CPU is pinned: An underpowered device, not the network.
  • Everything flat and healthy but user still complained: Look back at sections 3 and 4. The call may have taken too long to connect, or connected over a slow relay.

Putting It Together

The method is always the same: confirm media exists (1-2), confirm negotiation and connection (3-4), then read RTP stats and graphs to separate network problems (loss, jitter, RTT) from media problems (qualityLimitationReason: cpu, resolution drops) from connectivity problems (ICE failed, all-relay). Most "bad call" tickets resolve to one of those three buckets.

If you'd rather not parse JSON by hand, rtcStats reads a webrtc-internals dump and surfaces the same findings automatically: flags the observations above, scores the call's experience, and explains in plain language. Upload the dump in the browser and get the read without the manual pass. Either way, now you know what the tool is looking at.

The open source piece of rtcStats enables you to systematically collect webrtc-internals-like dumps (called rtcstats files) in your WebRTC deployment, so every call is counted, logged, and analyzed.