rtpbench conformance cases: livekit

date 2026-10-19T17:41:27+00:00, image rtpbench:72e41c264960, commit v0.1.0-15-g1c161cf, runs 10, kernel 6.8.0-147-generic, python 3.14.8

True value = measured − error; the error lies within:

Wall-clock steps during the run: none.

Turn latency, livekit

Turn latency, ms: caller's labelled end to the agent's first speech (webrtcvad), every turn of every run. True value = measured - error, error within the onset bar; where the caller's speech ends is defined to ±17 ms (label threshold ±5 dB).

profilerunsansweredp5p50p95run mediansacross a clock steponset error bar
clean10120/1201710183318921822 .. 18370[-3.2, +44.6] webrtcvad onset, p5..p95, PCMU, clean (calibrate --speech, seeds 1-5)
lte10120/1201879198420651947 .. 20020[-3.6, +43.3] webrtcvad onset, p5..p95, PCMU, lte (calibrate --speech, seeds 1-5)
lte-bad10120/1201956213523092089 .. 21980[-15.5, +60.9] webrtcvad onset, p5..p95, PCMU, lte-bad (calibrate --speech, seeds 1-5)

Each turn: a line of PROFILE/REPEAT/latency/turns.jsonl (results.json holds the cases only; rtpbench check gathers the turns into check.json).

Barge-in, livekit

Barge-in: whether the agent stopped within 2 s of the interjection's onset, and its stop time (ms, gate, wire) when it did, every turn of every run. True value = measured - error, error within the bar (calibrated on hard cuts). Speech ended before (gate): turns left out, the gate having heard the agent's speech end before the onset by more than the bar.

profileinterjectionrunsstoppedrun ratesp5p50p95across a clock stepspeech ended before (gate)stop error bar
cleaninterrupt1050/50100% .. 100%1129645401[-84.8, +0.0] gate stop time, p5..p95, PCMU, clean (calibrate --barge-in, seeds 1-5)
cleanbackchannel1025/25100% .. 100%028538300[-84.8, +0.0] gate stop time, p5..p95, PCMU, clean (calibrate --barge-in, seeds 1-5)
cleancough1022/22100% .. 100%3424743502[-84.8, +0.0] gate stop time, p5..p95, PCMU, clean (calibrate --barge-in, seeds 1-5)
lteinterrupt1051/51100% .. 100%3245764800[-81.9, +0.0] gate stop time, p5..p95, PCMU, lte (calibrate --barge-in, seeds 1-5)
ltebackchannel1025/25100% .. 100%22942457500[-81.9, +0.0] gate stop time, p5..p95, PCMU, lte (calibrate --barge-in, seeds 1-5)
ltecough1024/24100% .. 100%10440362700[-81.9, +0.0] gate stop time, p5..p95, PCMU, lte (calibrate --barge-in, seeds 1-5)
lte-badinterrupt1051/51100% .. 100%18462481800[-104.9, +0.0] gate stop time, p5..p95, PCMU, lte-bad (calibrate --barge-in, seeds 1-5)
lte-badbackchannel1025/25100% .. 100%42055175300[-104.9, +0.0] gate stop time, p5..p95, PCMU, lte-bad (calibrate --barge-in, seeds 1-5)
lte-badcough1024/24100% .. 100%17056174200[-104.9, +0.0] gate stop time, p5..p95, PCMU, lte-bad (calibrate --barge-in, seeds 1-5)

Per clip: stopped / turns, over the same turns, and those left out as ended before; interruptions are the caller's lines (--lines), backchannels and coughs the corpus's.

interjectionclipwordscleanltelte-bad
interruptinterrupt-0017/1717/1717/17
interruptinterrupt-0114/1414/1414/14
interruptinterrupt-0212/1212/1212/12
interruptinterrupt-037/7, 1 ended before8/88/8
backchanneltts-ald-bcAjá2/22/22/2
backchanneltts-cori-bcYeah3/33/33/3
backchanneltts-davefx-bcVale1/11/11/1
backchanneltts-libritts0-bcOkay4/44/44/4
backchanneltts-libritts3-bcUh-huh1/11/11/1
backchanneltts-ljspeech-bcUh-huh6/66/66/6
backchanneltts-sharvardf-bcVale5/55/55/5
backchanneltts-sharvardm-bcSí, sí3/33/33/3
coughcough-c1-13/33/33/3
coughcough-c2-03/33/33/3
coughcough-c2-12/22/22/2
coughcough-man-02/2, 1 ended before3/33/3
coughcough-man-13/33/33/3
coughcough-short-05/5, 1 ended before6/66/6
coughcough-short-12/22/22/2
coughcough-woman_three_times-02/22/22/2

Each turn: a line of PROFILE/REPEAT/barge-in/turns.jsonl (results.json holds the cases only; rtpbench check gathers the turns into check.json).

Turn latency by part, livekit

Turn latency on the mock engine, split where it heard the end of the caller's speech and sent its first audio (one clock with the captures), ms, p50 [p5, p95]: uplink and downlink are the target's; the engine waits 1000 ms of silence and answers 500 ms later by design. Uplink carries the caller's label error (±17 ms), downlink the onset error bar of the profile and codec.

profileturnswire latencyuplinkenginedownlink
clean1201833 [1710, 1892]190 [63, 205]1501 [1501, 1502]143 [130, 190]
lte1201984 [1879, 2065]294 [185, 350]1501 [1501, 1502]187 [167, 236]
lte-bad1202135 [1956, 2309]439 [253, 612]1501 [1501, 1502]193 [153, 251]

RTP pacing, livekit

The agent's RTP as the caller received it, ms, median [min, max] over calls: late, p99 of how much later than their timestamps say the packets arrived, against the earliest before them: the jitter buffer a receiver needs to play 99% of them in time; jitter, the RFC 3550 interarrival jitter estimate, its median over each call. On a clean network both are the agent's own pacing (and a carrier's); a profile adds its own.

profilecallslate, p99jitter
clean2021.0 [20.6, 21.5]0.13 [0.08, 0.36]
lte2034.8 [32.7, 37.4]3.36 [3.32, 3.46]
lte-bad20126.7 [123.7, 128.5]20.44 [20.23, 20.73]

Pauses: none; outside a hold, the agent's RTP never went on after stopping for a second or more.

Engine audio as the caller received it, livekit

The mock engine's answers as the caller received them (completed answers in the latency and barge-in calls), median [min, max] over answers. Each piece of speech is aligned with what the mock sent; for 24 kHz audio, that is its interpolation through an ideal 8 kHz converter, so the mock's own resampling is not counted. Samples in packets the network lost are left out. unchanged: answers whose aligned speech came through sample for sample (pauses are not compared). distortion: the audio against what no linear filter of ±4 ms explains; a resampler or band filter would leave G.711's own, about 37 dB. moved: answers where a piece came out 5 ms or more later or earlier than the one before (a pause lengthened or shortened, audio inserted or dropped), and the largest move. gain: least squares. 3.4-4 kHz: that band against 300-3400 Hz, relative to what was sent.

profileanswersunchangeddistortion, dBmovedgain, dB3.4-4 kHz, dB
clean240027.4 [13.7, 29.8]24, up to 40 ms-0.2 [-0.5, -0.0]-8.3 [-10.0, -7.5]
lte240027.3 [8.8, 30.1]23, up to 60 ms-0.2 [-0.7, -0.0]-8.3 [-11.4, -7.3]
lte-bad236027.1 [21.0, 30.2]18, up to 40 ms-0.2 [-0.7, -0.0]-10.0 [-14.9, +6.6]

Caller audio as the engine received it, livekit

The caller's lines in the latency and barge-in calls as the mock engine received them, aligned piece by piece with what the caller sent (its own capture, before the network), median [min, max] over lines; the columns as for the engine's audio above. Lost packets are the target's to fill: what it filled them with counts as distortion, and what it left out as moved. above 4 kHz: energy above 4 kHz against 300-3400 Hz in 24 kHz audio (the caller sends none). full scale: lines with samples at full scale. missing 20 ms: the caller's voiced 20 ms with nothing like them within 25 ms in what the engine got, and what came in their place: silence, the 20 ms before again (repeat), or other (also the next audio, where a packet was left out: see moved). appends: the audio each append carried, the median of each call's.

profilelinesunchangeddistortion, dBmovedgain, dB3.4-4 kHz, dBabove 4 kHz, dBfull scalemissing 20 msappends, ms
clean320028.3 [17.3, 31.1]0+1.9 [-0.4, +11.7]-16.6 [-22.9, -9.9]-60.7 [-62.6, -50.3]20, up to 7 samples0.4%: 63 other100 [100, 100]
lte309019.1 [-1.5, 31.2]132, up to 60 ms+1.6 [-2.7, +11.7]-16.6 [-22.1, -10.3]-60.7 [-62.7, -49.9]17, up to 7 samples0.9%: 9 silence, 4 repeat, 131 other100 [100, 100]
lte-bad23603.9 [-2.0, 30.4]174, up to 60 ms-0.3 [-4.0, +10.8]-16.7 [-24.6, -9.4]-60.8 [-62.8, -50.0]8, up to 9 samples3.8%: 64 silence, 1 repeat, 333 other100 [100, 100]

Calls

calleragenttall bars: speech · thin: RTP flowing · ticks: SIP (hover for detail)