WebRTC choppy audio: causes and how to diagnose it
Why WebRTC audio sounds robotic or breaks up, which getStats metrics show it, and how to tell jitter from packet loss.
Ever had a live call where the audio sounded robotic, or kept cutting out, or broke into little glitches? When users complain about such issues in WebRTC, what we do is open webrtc-internals, and start looking for the cause.
What we will do here is explain what choppy audio is in WebRTC, what causes it, which getStats() metrics to read, and how to tell a jitter problem apart from a packet loss problem.
What choppy audio actually is
When the audio pipeline does not have the next real sample ready to play, it cannot simply go silent, so it conceals the gap: it stretches, fabricates, or repeats audio to cover the missing piece. A little of this is inaudible. A lot of it is what your user hears as robotic, warbling, or breaking-up audio.
WebRTC counts this concealment directly:
inbound-rtp.concealedSamples: audio samples that were faked to cover a gap.inbound-rtp.concealmentEvents: how many distinct times concealment kicked in.concealment as a percentage of samples: the share of audio that was concealed, which is the number that tracks how bad it sounded.
In many cases, choppy audio is a downstream symptom of packet loss - when audio packets go missing and cannot be retransmitted in time, the pipeline has nothing real to play, so it fills the gap with concealment. Where packet loss indicates a technical problem, the concealment you hear is what translates it into a user problem.
What causes it
Choppy audio is almost always a downstream symptom of one of two upstream problems, plus a few local ones:
- Jitter. When packets arrive unevenly, the jitter buffer runs dry and the pipeline conceals the gap. See the jitter guide.
- Packet loss. Missing audio packets are concealed if they cannot be recovered in time. See the packet loss guide.
- A jitter buffer set too small, so it cannot absorb normal variance and underruns.
- Local audio device or CPU problems on the receiver that starve the pipeline even when the network is clean.
- Clock drift between the two endpoints, forcing frequent tiny corrections.
How to diagnose it
Read the concealment metrics first, then look upstream to find what caused the gaps.
| Metric | Healthy | Trouble |
|---|---|---|
| concealment percentage | low, a fraction of a percent | several percent or more |
concealmentEvents |
occasional | frequent and clustered |
jitter alongside concealment |
low | high when concealment rises |
packetsLost alongside concealment |
near zero | rising when concealment rises |
The correlation is what points at the cause:
- Concealment rises with jitter, loss near zero: the buffer is underrunning because packets arrive unevenly. It is a jitter problem, fix it there.
- Concealment rises with packet loss: the gaps are missing packets, not late ones. It is a packet loss problem.
- Concealment high, both jitter and loss low: the network delivered the audio, so look local: the receiver device, CPU, or clock drift.
- Steady low concealment: normal. Do not chase it.
Do this over time so you can see which upstream metric moves together with the concealment.
How rtcStats surfaces it
Tracing choppy audio back to jitter or loss by hand in webrtc-internals means correlating three timelines at once. rtcStats reads the dump for you: it flags the concealment burst as an Observation, ties it to whether jitter or packet loss was driving it as a Deduction, and reflects how the audio actually sounded in the Experience Score. The AI Summary gives you the one-paragraph version to paste into your bug thread.
Related
- inbound-rtp.concealedSamples
- inbound-rtp.concealmentEvents
- concealedSamples (%)
- WebRTC jitter
- WebRTC packet loss
Upload a webrtc-internals or rtcstats dump and rtcStats tells you whether the choppiness was jitter or loss, free.
Was this page helpful?