Schema 3.2.0
Entirely additive on the record level: no field was removed or renamed. Several counters were
widened from int to long.
Added — ECN and RFC 8888 congestion feedback
Explicit Congestion Notification lets the network mark packets as “congestion experienced” instead of dropping them, and RFC 8888 defines the feedback report that carries per-packet arrival information back to the sender. Together they are the foundation of L4S-style congestion control.
InboundRtpStats
| Field | Type | Description |
|---|---|---|
packetsReceivedWithEct1 | int optional | Total RTP packets received for this SSRC marked with the ECT(1) marking |
packetsReceivedWithCe | int optional | Total RTP packets received for this SSRC marked with the CE marking |
packetsReportedAsLost | int optional | Total RTP packets for which an RFC 8888 report has been sent with a zero R bit |
packetsReportedAsLostButRecovered | int optional | Total RTP packets reported as lost but later recovered in a subsequent RFC 8888 report |
RemoteInboundRtpStats
The same four fields, plus:
| Field | Type | Description |
|---|---|---|
packetsWithBleachedEct1Marking | long optional | Packets with ECT(1) marking that were bleached by a middlebox |
OutboundRtpStats
| Field | Type | Description |
|---|---|---|
packetsSentWithEct1 | long optional | Packets sent with ECT(1) congestion marking |
IceTransportStats
| Field | Type | Description |
|---|---|---|
ccfbMessagesSent | long optional | Congestion Control Feedback messages sent on this transport |
ccfbMessagesReceived | long optional | Congestion Control Feedback messages received on this transport |
Sparse by nature
Only browsers implementing ECN and RFC 8888 populate these. Treat every one of them as optional in your processing — most samples in the field will not carry them for some time.
packetsWithBleachedEct1Marking is the interesting one operationally: it says a middlebox on the
path stripped the ECN marking, which silently disables the congestion signalling you thought you
had.
Added — video quality measurement
PsnrSum (new record)
Peak signal-to-noise ratio per colour plane, nested in OutboundRtpStats.psnrSum.
| Field | Type | Description |
|---|---|---|
y | double | PSNR value for the Y (luminance) component |
u | double | PSNR value for the U (chrominance) component |
v | double | PSNR value for the V (chrominance) component |
OutboundRtpStats
| Field | Type | Description |
|---|---|---|
psnrSum | PsnrSum optional | Cumulative PSNR measurements for Y, U, V components |
psnrMeasurements | long optional | Total number of PSNR measurements collected |
encodingIndex | int optional | Index of the encoding in the encodings array |
encodingIndex is small but useful for simulcast: it identifies which configured encoding an
outbound RTP stream corresponds to, without inferring it from rid or resolution.
Divide psnrSum by psnrMeasurements for the average PSNR per plane over the session.
Changed — qualityLimitationDurations
Restructured from a loose map into a named record:
type QualityLimitationDurations = {
none: number; // seconds with no quality limitation
cpu: number; // seconds limited by CPU
bandwidth: number; // seconds limited by bandwidth
other: number; // seconds limited for other reasons
};Why this matters for analysis
qualityLimitationReason tells you what is limiting the encoder right now — a single sample of a
state that flickers. qualityLimitationDurations is cumulative, so differencing it across two
samples gives you how many seconds of this interval were CPU-limited versus bandwidth-limited.
That is the number that actually answers “was this call CPU-bound or network-bound?”.
CallHealthAggregator in observer-js
surfaces exactly this as health.qualityLimitation.
Changed — counter widening
Byte and packet counters that could realistically exceed 32 bits on long, high-bitrate sessions
were widened from int to long across the inbound, remote-inbound, outbound and transport
records.
Changed — infrastructure
frozenadded as a state onIceCandidatePairStats.- Node 22 across the CI workflows.
- Protobuf handling reworked, dependencies updated,
CONTRIBUTING.mdadded.
Compatibility
Additive on the record level, but remember that protobuf field numbers derive from sorted field order — new fields inserted before existing ones in the sort renumber what follows. Keep encoder and decoder on matching versions.
← Back to version history · 3.1.0 →