github.com/pion/webrtc/v4@v4.0.1/stats.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package webrtc 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "sync" 10 "time" 11 12 "github.com/pion/ice/v4" 13 ) 14 15 // A Stats object contains a set of statistics copies out of a monitored component 16 // of the WebRTC stack at a specific time. 17 type Stats interface { 18 statsMarker() 19 } 20 21 // UnmarshalStatsJSON unmarshals a Stats object from JSON 22 func UnmarshalStatsJSON(b []byte) (Stats, error) { 23 type typeJSON struct { 24 Type StatsType `json:"type"` 25 } 26 typeHolder := typeJSON{} 27 28 err := json.Unmarshal(b, &typeHolder) 29 if err != nil { 30 return nil, fmt.Errorf("unmarshal json type: %w", err) 31 } 32 33 switch typeHolder.Type { 34 case StatsTypeCodec: 35 return unmarshalCodecStats(b) 36 case StatsTypeInboundRTP: 37 return unmarshalInboundRTPStreamStats(b) 38 case StatsTypeOutboundRTP: 39 return unmarshalOutboundRTPStreamStats(b) 40 case StatsTypeRemoteInboundRTP: 41 return unmarshalRemoteInboundRTPStreamStats(b) 42 case StatsTypeRemoteOutboundRTP: 43 return unmarshalRemoteOutboundRTPStreamStats(b) 44 case StatsTypeCSRC: 45 return unmarshalCSRCStats(b) 46 case StatsTypeMediaSource: 47 return unmarshalMediaSourceStats(b) 48 case StatsTypeMediaPlayout: 49 return unmarshalMediaPlayoutStats(b) 50 case StatsTypePeerConnection: 51 return unmarshalPeerConnectionStats(b) 52 case StatsTypeDataChannel: 53 return unmarshalDataChannelStats(b) 54 case StatsTypeStream: 55 return unmarshalStreamStats(b) 56 case StatsTypeTrack: 57 return unmarshalTrackStats(b) 58 case StatsTypeSender: 59 return unmarshalSenderStats(b) 60 case StatsTypeReceiver: 61 return unmarshalReceiverStats(b) 62 case StatsTypeTransport: 63 return unmarshalTransportStats(b) 64 case StatsTypeCandidatePair: 65 return unmarshalICECandidatePairStats(b) 66 case StatsTypeLocalCandidate, StatsTypeRemoteCandidate: 67 return unmarshalICECandidateStats(b) 68 case StatsTypeCertificate: 69 return unmarshalCertificateStats(b) 70 case StatsTypeSCTPTransport: 71 return unmarshalSCTPTransportStats(b) 72 default: 73 return nil, fmt.Errorf("type: %w", ErrUnknownType) 74 } 75 } 76 77 // StatsType indicates the type of the object that a Stats object represents. 78 type StatsType string 79 80 const ( 81 // StatsTypeCodec is used by CodecStats. 82 StatsTypeCodec StatsType = "codec" 83 84 // StatsTypeInboundRTP is used by InboundRTPStreamStats. 85 StatsTypeInboundRTP StatsType = "inbound-rtp" 86 87 // StatsTypeOutboundRTP is used by OutboundRTPStreamStats. 88 StatsTypeOutboundRTP StatsType = "outbound-rtp" 89 90 // StatsTypeRemoteInboundRTP is used by RemoteInboundRTPStreamStats. 91 StatsTypeRemoteInboundRTP StatsType = "remote-inbound-rtp" 92 93 // StatsTypeRemoteOutboundRTP is used by RemoteOutboundRTPStreamStats. 94 StatsTypeRemoteOutboundRTP StatsType = "remote-outbound-rtp" 95 96 // StatsTypeCSRC is used by RTPContributingSourceStats. 97 StatsTypeCSRC StatsType = "csrc" 98 99 // StatsTypeMediaSource is used by AudioSourceStats or VideoSourceStats depending on kind. 100 StatsTypeMediaSource = "media-source" 101 102 // StatsTypeMediaPlayout is used by AudioPlayoutStats. 103 StatsTypeMediaPlayout StatsType = "media-playout" 104 105 // StatsTypePeerConnection used by PeerConnectionStats. 106 StatsTypePeerConnection StatsType = "peer-connection" 107 108 // StatsTypeDataChannel is used by DataChannelStats. 109 StatsTypeDataChannel StatsType = "data-channel" 110 111 // StatsTypeStream is used by MediaStreamStats. 112 StatsTypeStream StatsType = "stream" 113 114 // StatsTypeTrack is used by SenderVideoTrackAttachmentStats and SenderAudioTrackAttachmentStats depending on kind. 115 StatsTypeTrack StatsType = "track" 116 117 // StatsTypeSender is used by the AudioSenderStats or VideoSenderStats depending on kind. 118 StatsTypeSender StatsType = "sender" 119 120 // StatsTypeReceiver is used by the AudioReceiverStats or VideoReceiverStats depending on kind. 121 StatsTypeReceiver StatsType = "receiver" 122 123 // StatsTypeTransport is used by TransportStats. 124 StatsTypeTransport StatsType = "transport" 125 126 // StatsTypeCandidatePair is used by ICECandidatePairStats. 127 StatsTypeCandidatePair StatsType = "candidate-pair" 128 129 // StatsTypeLocalCandidate is used by ICECandidateStats for the local candidate. 130 StatsTypeLocalCandidate StatsType = "local-candidate" 131 132 // StatsTypeRemoteCandidate is used by ICECandidateStats for the remote candidate. 133 StatsTypeRemoteCandidate StatsType = "remote-candidate" 134 135 // StatsTypeCertificate is used by CertificateStats. 136 StatsTypeCertificate StatsType = "certificate" 137 138 // StatsTypeSCTPTransport is used by SCTPTransportStats 139 StatsTypeSCTPTransport StatsType = "sctp-transport" 140 ) 141 142 // MediaKind indicates the kind of media (audio or video) 143 type MediaKind string 144 145 const ( 146 // MediaKindAudio indicates this is audio stats 147 MediaKindAudio MediaKind = "audio" 148 // MediaKindVideo indicates this is video stats 149 MediaKindVideo MediaKind = "video" 150 ) 151 152 // StatsTimestamp is a timestamp represented by the floating point number of 153 // milliseconds since the epoch. 154 type StatsTimestamp float64 155 156 // Time returns the time.Time represented by this timestamp. 157 func (s StatsTimestamp) Time() time.Time { 158 millis := float64(s) 159 nanos := int64(millis * float64(time.Millisecond)) 160 161 return time.Unix(0, nanos).UTC() 162 } 163 164 func statsTimestampFrom(t time.Time) StatsTimestamp { 165 return StatsTimestamp(t.UnixNano() / int64(time.Millisecond)) 166 } 167 168 func statsTimestampNow() StatsTimestamp { 169 return statsTimestampFrom(time.Now()) 170 } 171 172 // StatsReport collects Stats objects indexed by their ID. 173 type StatsReport map[string]Stats 174 175 type statsReportCollector struct { 176 collectingGroup sync.WaitGroup 177 report StatsReport 178 mux sync.Mutex 179 } 180 181 func newStatsReportCollector() *statsReportCollector { 182 return &statsReportCollector{report: make(StatsReport)} 183 } 184 185 func (src *statsReportCollector) Collecting() { 186 src.collectingGroup.Add(1) 187 } 188 189 func (src *statsReportCollector) Collect(id string, stats Stats) { 190 src.mux.Lock() 191 defer src.mux.Unlock() 192 193 src.report[id] = stats 194 src.collectingGroup.Done() 195 } 196 197 func (src *statsReportCollector) Done() { 198 src.collectingGroup.Done() 199 } 200 201 func (src *statsReportCollector) Ready() StatsReport { 202 src.collectingGroup.Wait() 203 src.mux.Lock() 204 defer src.mux.Unlock() 205 return src.report 206 } 207 208 // CodecType specifies whether a CodecStats objects represents a media format 209 // that is being encoded or decoded 210 type CodecType string 211 212 const ( 213 // CodecTypeEncode means the attached CodecStats represents a media format that 214 // is being encoded, or that the implementation is prepared to encode. 215 CodecTypeEncode CodecType = "encode" 216 217 // CodecTypeDecode means the attached CodecStats represents a media format 218 // that the implementation is prepared to decode. 219 CodecTypeDecode CodecType = "decode" 220 ) 221 222 // CodecStats contains statistics for a codec that is currently being used by RTP streams 223 // being sent or received by this PeerConnection object. 224 type CodecStats struct { 225 // Timestamp is the timestamp associated with this object. 226 Timestamp StatsTimestamp `json:"timestamp"` 227 228 // Type is the object's StatsType 229 Type StatsType `json:"type"` 230 231 // ID is a unique id that is associated with the component inspected to produce 232 // this Stats object. Two Stats objects will have the same ID if they were produced 233 // by inspecting the same underlying object. 234 ID string `json:"id"` 235 236 // PayloadType as used in RTP encoding or decoding 237 PayloadType PayloadType `json:"payloadType"` 238 239 // CodecType of this CodecStats 240 CodecType CodecType `json:"codecType"` 241 242 // TransportID is the unique identifier of the transport on which this codec is 243 // being used, which can be used to look up the corresponding TransportStats object. 244 TransportID string `json:"transportId"` 245 246 // MimeType is the codec MIME media type/subtype. e.g., video/vp8 or equivalent. 247 MimeType string `json:"mimeType"` 248 249 // ClockRate represents the media sampling rate. 250 ClockRate uint32 `json:"clockRate"` 251 252 // Channels is 2 for stereo, missing for most other cases. 253 Channels uint8 `json:"channels"` 254 255 // SDPFmtpLine is the a=fmtp line in the SDP corresponding to the codec, 256 // i.e., after the colon following the PT. 257 SDPFmtpLine string `json:"sdpFmtpLine"` 258 259 // Implementation identifies the implementation used. This is useful for diagnosing 260 // interoperability issues. 261 Implementation string `json:"implementation"` 262 } 263 264 func (s CodecStats) statsMarker() {} 265 266 func unmarshalCodecStats(b []byte) (CodecStats, error) { 267 var codecStats CodecStats 268 err := json.Unmarshal(b, &codecStats) 269 if err != nil { 270 return CodecStats{}, fmt.Errorf("unmarshal codec stats: %w", err) 271 } 272 return codecStats, nil 273 } 274 275 // InboundRTPStreamStats contains statistics for an inbound RTP stream that is 276 // currently received with this PeerConnection object. 277 type InboundRTPStreamStats struct { 278 // Mid represents a mid value of RTPTransceiver owning this stream, if that value is not 279 // null. Otherwise, this member is not present. 280 Mid string `json:"mid"` 281 282 // Timestamp is the timestamp associated with this object. 283 Timestamp StatsTimestamp `json:"timestamp"` 284 285 // Type is the object's StatsType 286 Type StatsType `json:"type"` 287 288 // ID is a unique id that is associated with the component inspected to produce 289 // this Stats object. Two Stats objects will have the same ID if they were produced 290 // by inspecting the same underlying object. 291 ID string `json:"id"` 292 293 // SSRC is the 32-bit unsigned integer value used to identify the source of the 294 // stream of RTP packets that this stats object concerns. 295 SSRC SSRC `json:"ssrc"` 296 297 // Kind is either "audio" or "video" 298 Kind string `json:"kind"` 299 300 // It is a unique identifier that is associated to the object that was inspected 301 // to produce the TransportStats associated with this RTP stream. 302 TransportID string `json:"transportId"` 303 304 // CodecID is a unique identifier that is associated to the object that was inspected 305 // to produce the CodecStats associated with this RTP stream. 306 CodecID string `json:"codecId"` 307 308 // FIRCount counts the total number of Full Intra Request (FIR) packets received 309 // by the sender. This metric is only valid for video and is sent by receiver. 310 FIRCount uint32 `json:"firCount"` 311 312 // PLICount counts the total number of Picture Loss Indication (PLI) packets 313 // received by the sender. This metric is only valid for video and is sent by receiver. 314 PLICount uint32 `json:"pliCount"` 315 316 // TotalProcessingDelay is the sum of the time, in seconds, each audio sample or video frame 317 // takes from the time the first RTP packet is received (reception timestamp) and to the time 318 // the corresponding sample or frame is decoded (decoded timestamp). At this point the audio 319 // sample or video frame is ready for playout by the MediaStreamTrack. Typically ready for 320 // playout here means after the audio sample or video frame is fully decoded by the decoder. 321 TotalProcessingDelay float64 `json:"totalProcessingDelay"` 322 323 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 324 // received by the sender and is sent by receiver. 325 NACKCount uint32 `json:"nackCount"` 326 327 // JitterBufferDelay is the sum of the time, in seconds, each audio sample or a video frame 328 // takes from the time the first packet is received by the jitter buffer (ingest timestamp) 329 // to the time it exits the jitter buffer (emit timestamp). The average jitter buffer delay 330 // can be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. 331 JitterBufferDelay float64 `json:"jitterBufferDelay"` 332 333 // JitterBufferTargetDelay is increased by the target jitter buffer delay every time a sample is emitted 334 // by the jitter buffer. The added target is the target delay, in seconds, at the time that 335 // the sample was emitted from the jitter buffer. To get the average target delay, 336 // divide by JitterBufferEmittedCount 337 JitterBufferTargetDelay float64 `json:"jitterBufferTargetDelay"` 338 339 // JitterBufferEmittedCount is the total number of audio samples or video frames that 340 // have come out of the jitter buffer (increasing jitterBufferDelay). 341 JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` 342 343 // JitterBufferMinimumDelay works the same way as jitterBufferTargetDelay, except that 344 // it is not affected by external mechanisms that increase the jitter buffer target delay, 345 // such as jitterBufferTarget, AV sync, or any other mechanisms. This metric is purely 346 // based on the network characteristics such as jitter and packet loss, and can be seen 347 // as the minimum obtainable jitter buffer delay if no external factors would affect it. 348 // The metric is updated every time JitterBufferEmittedCount is updated. 349 JitterBufferMinimumDelay float64 `json:"jitterBufferMinimumDelay"` 350 351 // TotalSamplesReceived is the total number of samples that have been received on 352 // this RTP stream. This includes concealedSamples. Does not exist for video. 353 TotalSamplesReceived uint64 `json:"totalSamplesReceived"` 354 355 // ConcealedSamples is the total number of samples that are concealed samples. 356 // A concealed sample is a sample that was replaced with synthesized samples generated 357 // locally before being played out. Examples of samples that have to be concealed are 358 // samples from lost packets (reported in packetsLost) or samples from packets that 359 // arrive too late to be played out (reported in packetsDiscarded). Does not exist for video. 360 ConcealedSamples uint64 `json:"concealedSamples"` 361 362 // SilentConcealedSamples is the total number of concealed samples inserted that 363 // are "silent". Playing out silent samples results in silence or comfort noise. 364 // This is a subset of concealedSamples. Does not exist for video. 365 SilentConcealedSamples uint64 `json:"silentConcealedSamples"` 366 367 // ConcealmentEvents increases every time a concealed sample is synthesized after 368 // a non-concealed sample. That is, multiple consecutive concealed samples will increase 369 // the concealedSamples count multiple times but is a single concealment event. 370 // Does not exist for video. 371 ConcealmentEvents uint64 `json:"concealmentEvents"` 372 373 // InsertedSamplesForDeceleration is increased by the difference between the number of 374 // samples received and the number of samples played out when playout is slowed down. 375 // If playout is slowed down by inserting samples, this will be the number of inserted samples. 376 // Does not exist for video. 377 InsertedSamplesForDeceleration uint64 `json:"insertedSamplesForDeceleration"` 378 379 // RemovedSamplesForAcceleration is increased by the difference between the number of 380 // samples received and the number of samples played out when playout is sped up. If speedup 381 // is achieved by removing samples, this will be the count of samples removed. 382 // Does not exist for video. 383 RemovedSamplesForAcceleration uint64 `json:"removedSamplesForAcceleration"` 384 385 // AudioLevel represents the audio level of the receiving track.. 386 // 387 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 388 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 389 // the sound pressure level from 0 dBov. Does not exist for video. 390 AudioLevel float64 `json:"audioLevel"` 391 392 // TotalAudioEnergy represents the audio energy of the receiving track. It is calculated 393 // by duration * Math.pow(energy/maxEnergy, 2) for each audio sample received (and thus 394 // counted by TotalSamplesReceived). Does not exist for video. 395 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 396 397 // TotalSamplesDuration represents the total duration in seconds of all samples that have been 398 // received (and thus counted by TotalSamplesReceived). Can be used with totalAudioEnergy to 399 // compute an average audio level over different intervals. Does not exist for video. 400 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 401 402 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 403 // by the sender. This metric is only valid for video and is sent by receiver. 404 SLICount uint32 `json:"sliCount"` 405 406 // QPSum is the sum of the QP values of frames passed. The count of frames is 407 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 408 QPSum uint64 `json:"qpSum"` 409 410 // TotalDecodeTime is the total number of seconds that have been spent decoding the FramesDecoded 411 // frames of this stream. The average decode time can be calculated by dividing this value 412 // with FramesDecoded. The time it takes to decode one frame is the time passed between 413 // feeding the decoder a frame and the decoder returning decoded data for that frame. 414 TotalDecodeTime float64 `json:"totalDecodeTime"` 415 416 // TotalInterFrameDelay is the sum of the interframe delays in seconds between consecutively 417 // rendered frames, recorded just after a frame has been rendered. The interframe delay variance 418 // be calculated from TotalInterFrameDelay, TotalSquaredInterFrameDelay, and FramesRendered according 419 // to the formula: (TotalSquaredInterFrameDelay - TotalInterFrameDelay^2 / FramesRendered) / FramesRendered. 420 // Does not exist for audio. 421 TotalInterFrameDelay float64 `json:"totalInterFrameDelay"` 422 423 // TotalSquaredInterFrameDelay is the sum of the squared interframe delays in seconds 424 // between consecutively rendered frames, recorded just after a frame has been rendered. 425 // See TotalInterFrameDelay for details on how to calculate the interframe delay variance. 426 // Does not exist for audio. 427 TotalSquaredInterFrameDelay float64 `json:"totalSquaredInterFrameDelay"` 428 429 // PacketsReceived is the total number of RTP packets received for this SSRC. 430 PacketsReceived uint32 `json:"packetsReceived"` 431 432 // PacketsLost is the total number of RTP packets lost for this SSRC. Note that 433 // because of how this is estimated, it can be negative if more packets are received than sent. 434 PacketsLost int32 `json:"packetsLost"` 435 436 // Jitter is the packet jitter measured in seconds for this SSRC 437 Jitter float64 `json:"jitter"` 438 439 // PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter 440 // buffer due to late or early-arrival, i.e., these packets are not played out. 441 // RTP packets discarded due to packet duplication are not reported in this metric. 442 PacketsDiscarded uint32 `json:"packetsDiscarded"` 443 444 // PacketsRepaired is the cumulative number of lost RTP packets repaired after applying 445 // an error-resilience mechanism. It is measured for the primary source RTP packets 446 // and only counted for RTP packets that have no further chance of repair. 447 PacketsRepaired uint32 `json:"packetsRepaired"` 448 449 // BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts. 450 BurstPacketsLost uint32 `json:"burstPacketsLost"` 451 452 // BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts. 453 BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"` 454 455 // BurstLossCount is the cumulative number of bursts of lost RTP packets. 456 BurstLossCount uint32 `json:"burstLossCount"` 457 458 // BurstDiscardCount is the cumulative number of bursts of discarded RTP packets. 459 BurstDiscardCount uint32 `json:"burstDiscardCount"` 460 461 // BurstLossRate is the fraction of RTP packets lost during bursts to the 462 // total number of RTP packets expected in the bursts. 463 BurstLossRate float64 `json:"burstLossRate"` 464 465 // BurstDiscardRate is the fraction of RTP packets discarded during bursts to 466 // the total number of RTP packets expected in bursts. 467 BurstDiscardRate float64 `json:"burstDiscardRate"` 468 469 // GapLossRate is the fraction of RTP packets lost during the gap periods. 470 GapLossRate float64 `json:"gapLossRate"` 471 472 // GapDiscardRate is the fraction of RTP packets discarded during the gap periods. 473 GapDiscardRate float64 `json:"gapDiscardRate"` 474 475 // TrackID is the identifier of the stats object representing the receiving track, 476 // a ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats. 477 TrackID string `json:"trackId"` 478 479 // ReceiverID is the stats ID used to look up the AudioReceiverStats or VideoReceiverStats 480 // object receiving this stream. 481 ReceiverID string `json:"receiverId"` 482 483 // RemoteID is used for looking up the remote RemoteOutboundRTPStreamStats object 484 // for the same SSRC. 485 RemoteID string `json:"remoteId"` 486 487 // FramesDecoded represents the total number of frames correctly decoded for this SSRC, 488 // i.e., frames that would be displayed if no frames are dropped. Only valid for video. 489 FramesDecoded uint32 `json:"framesDecoded"` 490 491 // KeyFramesDecoded represents the total number of key frames, such as key frames in 492 // VP8 [RFC6386] or IDR-frames in H.264 [RFC6184], successfully decoded for this RTP 493 // media stream. This is a subset of FramesDecoded. FramesDecoded - KeyFramesDecoded 494 // gives you the number of delta frames decoded. Does not exist for audio. 495 KeyFramesDecoded uint32 `json:"keyFramesDecoded"` 496 497 // FramesRendered represents the total number of frames that have been rendered. 498 // It is incremented just after a frame has been rendered. Does not exist for audio. 499 FramesRendered uint32 `json:"framesRendered"` 500 501 // FramesDropped is the total number of frames dropped prior to decode or dropped 502 // because the frame missed its display deadline for this receiver's track. 503 // The measurement begins when the receiver is created and is a cumulative metric 504 // as defined in Appendix A (g) of [RFC7004]. Does not exist for audio. 505 FramesDropped uint32 `json:"framesDropped"` 506 507 // FrameWidth represents the width of the last decoded frame. Before the first 508 // frame is decoded this member does not exist. Does not exist for audio. 509 FrameWidth uint32 `json:"frameWidth"` 510 511 // FrameHeight represents the height of the last decoded frame. Before the first 512 // frame is decoded this member does not exist. Does not exist for audio. 513 FrameHeight uint32 `json:"frameHeight"` 514 515 // LastPacketReceivedTimestamp represents the timestamp at which the last packet was 516 // received for this SSRC. This differs from Timestamp, which represents the time 517 // at which the statistics were generated by the local endpoint. 518 LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"` 519 520 // HeaderBytesReceived is the total number of RTP header and padding bytes received for this SSRC. 521 // This includes retransmissions. This does not include the size of transport layer headers such 522 // as IP or UDP. headerBytesReceived + bytesReceived equals the number of bytes received as 523 // payload over the transport. 524 HeaderBytesReceived uint64 `json:"headerBytesReceived"` 525 526 // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP packets. 527 // This is calculated by the sending endpoint when sending compound RTCP reports. 528 // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet 529 // with the CNAME item. 530 AverageRTCPInterval float64 `json:"averageRtcpInterval"` 531 532 // FECPacketsReceived is the total number of RTP FEC packets received for this SSRC. 533 // This counter can also be incremented when receiving FEC packets in-band with media packets (e.g., with Opus). 534 FECPacketsReceived uint32 `json:"fecPacketsReceived"` 535 536 // FECPacketsDiscarded is the total number of RTP FEC packets received for this SSRC where the 537 // error correction payload was discarded by the application. This may happen 538 // 1. if all the source packets protected by the FEC packet were received or already 539 // recovered by a separate FEC packet, or 540 // 2. if the FEC packet arrived late, i.e., outside the recovery window, and the 541 // lost RTP packets have already been skipped during playout. 542 // This is a subset of FECPacketsReceived. 543 FECPacketsDiscarded uint64 `json:"fecPacketsDiscarded"` 544 545 // BytesReceived is the total number of bytes received for this SSRC. 546 BytesReceived uint64 `json:"bytesReceived"` 547 548 // FramesReceived represents the total number of complete frames received on this RTP stream. 549 // This metric is incremented when the complete frame is received. Does not exist for audio. 550 FramesReceived uint32 `json:"framesReceived"` 551 552 // PacketsFailedDecryption is the cumulative number of RTP packets that failed 553 // to be decrypted. These packets are not counted by PacketsDiscarded. 554 PacketsFailedDecryption uint32 `json:"packetsFailedDecryption"` 555 556 // PacketsDuplicated is the cumulative number of packets discarded because they 557 // are duplicated. Duplicate packets are not counted in PacketsDiscarded. 558 // 559 // Duplicated packets have the same RTP sequence number and content as a previously 560 // received packet. If multiple duplicates of a packet are received, all of them are counted. 561 // An improved estimate of lost packets can be calculated by adding PacketsDuplicated to PacketsLost. 562 PacketsDuplicated uint32 `json:"packetsDuplicated"` 563 564 // PerDSCPPacketsReceived is the total number of packets received for this SSRC, 565 // per Differentiated Services code point (DSCP) [RFC2474]. DSCPs are identified 566 // as decimal integers in string form. Note that due to network remapping and bleaching, 567 // these numbers are not expected to match the numbers seen on sending. Not all 568 // OSes make this information available. 569 PerDSCPPacketsReceived map[string]uint32 `json:"perDscpPacketsReceived"` 570 } 571 572 func (s InboundRTPStreamStats) statsMarker() {} 573 574 func unmarshalInboundRTPStreamStats(b []byte) (InboundRTPStreamStats, error) { 575 var inboundRTPStreamStats InboundRTPStreamStats 576 err := json.Unmarshal(b, &inboundRTPStreamStats) 577 if err != nil { 578 return InboundRTPStreamStats{}, fmt.Errorf("unmarshal inbound rtp stream stats: %w", err) 579 } 580 return inboundRTPStreamStats, nil 581 } 582 583 // QualityLimitationReason lists the reason for limiting the resolution and/or framerate. 584 // Only valid for video. 585 type QualityLimitationReason string 586 587 const ( 588 // QualityLimitationReasonNone means the resolution and/or framerate is not limited. 589 QualityLimitationReasonNone QualityLimitationReason = "none" 590 591 // QualityLimitationReasonCPU means the resolution and/or framerate is primarily limited due to CPU load. 592 QualityLimitationReasonCPU QualityLimitationReason = "cpu" 593 594 // QualityLimitationReasonBandwidth means the resolution and/or framerate is primarily limited due to congestion cues during bandwidth estimation. Typical, congestion control algorithms use inter-arrival time, round-trip time, packet or other congestion cues to perform bandwidth estimation. 595 QualityLimitationReasonBandwidth QualityLimitationReason = "bandwidth" 596 597 // QualityLimitationReasonOther means the resolution and/or framerate is primarily limited for a reason other than the above. 598 QualityLimitationReasonOther QualityLimitationReason = "other" 599 ) 600 601 // OutboundRTPStreamStats contains statistics for an outbound RTP stream that is 602 // currently sent with this PeerConnection object. 603 type OutboundRTPStreamStats struct { 604 // Mid represents a mid value of RTPTransceiver owning this stream, if that value is not 605 // null. Otherwise, this member is not present. 606 Mid string `json:"mid"` 607 608 // Rid only exists if a rid has been set for this RTP stream. 609 // Must not exist for audio. 610 Rid string `json:"rid"` 611 612 // MediaSourceID is the identifier of the stats object representing the track currently 613 // attached to the sender of this stream, an RTCMediaSourceStats. 614 MediaSourceID string `json:"mediaSourceId"` 615 616 // Timestamp is the timestamp associated with this object. 617 Timestamp StatsTimestamp `json:"timestamp"` 618 619 // Type is the object's StatsType 620 Type StatsType `json:"type"` 621 622 // ID is a unique id that is associated with the component inspected to produce 623 // this Stats object. Two Stats objects will have the same ID if they were produced 624 // by inspecting the same underlying object. 625 ID string `json:"id"` 626 627 // SSRC is the 32-bit unsigned integer value used to identify the source of the 628 // stream of RTP packets that this stats object concerns. 629 SSRC SSRC `json:"ssrc"` 630 631 // Kind is either "audio" or "video" 632 Kind string `json:"kind"` 633 634 // It is a unique identifier that is associated to the object that was inspected 635 // to produce the TransportStats associated with this RTP stream. 636 TransportID string `json:"transportId"` 637 638 // CodecID is a unique identifier that is associated to the object that was inspected 639 // to produce the CodecStats associated with this RTP stream. 640 CodecID string `json:"codecId"` 641 642 // HeaderBytesSent is the total number of RTP header and padding bytes sent for this SSRC. This does not 643 // include the size of transport layer headers such as IP or UDP. 644 // HeaderBytesSent + BytesSent equals the number of bytes sent as payload over the transport. 645 HeaderBytesSent uint64 `json:"headerBytesSent"` 646 647 // RetransmittedPacketsSent is the total number of packets that were retransmitted for this SSRC. 648 // This is a subset of packetsSent. If RTX is not negotiated, retransmitted packets are sent 649 // over this ssrc. If RTX was negotiated, retransmitted packets are sent over a separate SSRC 650 // but is still accounted for here. 651 RetransmittedPacketsSent uint64 `json:"retransmittedPacketsSent"` 652 653 // RetransmittedBytesSent is the total number of bytes that were retransmitted for this SSRC, 654 // only including payload bytes. This is a subset of bytesSent. If RTX is not negotiated, 655 // retransmitted bytes are sent over this ssrc. If RTX was negotiated, retransmitted bytes 656 // are sent over a separate SSRC but is still accounted for here. 657 RetransmittedBytesSent uint64 `json:"retransmittedBytesSent"` 658 659 // FIRCount counts the total number of Full Intra Request (FIR) packets received 660 // by the sender. This metric is only valid for video and is sent by receiver. 661 FIRCount uint32 `json:"firCount"` 662 663 // PLICount counts the total number of Picture Loss Indication (PLI) packets 664 // received by the sender. This metric is only valid for video and is sent by receiver. 665 PLICount uint32 `json:"pliCount"` 666 667 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 668 // received by the sender and is sent by receiver. 669 NACKCount uint32 `json:"nackCount"` 670 671 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 672 // by the sender. This metric is only valid for video and is sent by receiver. 673 SLICount uint32 `json:"sliCount"` 674 675 // QPSum is the sum of the QP values of frames passed. The count of frames is 676 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 677 QPSum uint64 `json:"qpSum"` 678 679 // PacketsSent is the total number of RTP packets sent for this SSRC. 680 PacketsSent uint32 `json:"packetsSent"` 681 682 // PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that 683 // have been discarded due to socket errors, i.e. a socket error occurred when handing 684 // the packets to the socket. This might happen due to various reasons, including 685 // full buffer or no available memory. 686 PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` 687 688 // FECPacketsSent is the total number of RTP FEC packets sent for this SSRC. 689 // This counter can also be incremented when sending FEC packets in-band with 690 // media packets (e.g., with Opus). 691 FECPacketsSent uint32 `json:"fecPacketsSent"` 692 693 // BytesSent is the total number of bytes sent for this SSRC. 694 BytesSent uint64 `json:"bytesSent"` 695 696 // BytesDiscardedOnSend is the total number of bytes for this SSRC that have 697 // been discarded due to socket errors, i.e. a socket error occurred when handing 698 // the packets containing the bytes to the socket. This might happen due to various 699 // reasons, including full buffer or no available memory. 700 BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"` 701 702 // TrackID is the identifier of the stats object representing the current track 703 // attachment to the sender of this stream, a SenderAudioTrackAttachmentStats 704 // or SenderVideoTrackAttachmentStats. 705 TrackID string `json:"trackId"` 706 707 // SenderID is the stats ID used to look up the AudioSenderStats or VideoSenderStats 708 // object sending this stream. 709 SenderID string `json:"senderId"` 710 711 // RemoteID is used for looking up the remote RemoteInboundRTPStreamStats object 712 // for the same SSRC. 713 RemoteID string `json:"remoteId"` 714 715 // LastPacketSentTimestamp represents the timestamp at which the last packet was 716 // sent for this SSRC. This differs from timestamp, which represents the time at 717 // which the statistics were generated by the local endpoint. 718 LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"` 719 720 // TargetBitrate is the current target bitrate configured for this particular SSRC 721 // and is the Transport Independent Application Specific (TIAS) bitrate [RFC3890]. 722 // Typically, the target bitrate is a configuration parameter provided to the codec's 723 // encoder and does not count the size of the IP or other transport layers like TCP or UDP. 724 // It is measured in bits per second and the bitrate is calculated over a 1 second window. 725 TargetBitrate float64 `json:"targetBitrate"` 726 727 // TotalEncodedBytesTarget is increased by the target frame size in bytes every time 728 // a frame has been encoded. The actual frame size may be bigger or smaller than this number. 729 // This value goes up every time framesEncoded goes up. 730 TotalEncodedBytesTarget uint64 `json:"totalEncodedBytesTarget"` 731 732 // FrameWidth represents the width of the last encoded frame. The resolution of the 733 // encoded frame may be lower than the media source. Before the first frame is encoded 734 // this member does not exist. Does not exist for audio. 735 FrameWidth uint32 `json:"frameWidth"` 736 737 // FrameHeight represents the height of the last encoded frame. The resolution of the 738 // encoded frame may be lower than the media source. Before the first frame is encoded 739 // this member does not exist. Does not exist for audio. 740 FrameHeight uint32 `json:"frameHeight"` 741 742 // FramesPerSecond is the number of encoded frames during the last second. This may be 743 // lower than the media source frame rate. Does not exist for audio. 744 FramesPerSecond float64 `json:"framesPerSecond"` 745 746 // FramesSent represents the total number of frames sent on this RTP stream. Does not exist for audio. 747 FramesSent uint32 `json:"framesSent"` 748 749 // HugeFramesSent represents the total number of huge frames sent by this RTP stream. 750 // Huge frames, by definition, are frames that have an encoded size at least 2.5 times 751 // the average size of the frames. The average size of the frames is defined as the 752 // target bitrate per second divided by the target FPS at the time the frame was encoded. 753 // These are usually complex to encode frames with a lot of changes in the picture. 754 // This can be used to estimate, e.g slide changes in the streamed presentation. 755 // Does not exist for audio. 756 HugeFramesSent uint32 `json:"hugeFramesSent"` 757 758 // FramesEncoded represents the total number of frames successfully encoded for this RTP media stream. 759 // Only valid for video. 760 FramesEncoded uint32 `json:"framesEncoded"` 761 762 // KeyFramesEncoded represents the total number of key frames, such as key frames in VP8 [RFC6386] or 763 // IDR-frames in H.264 [RFC6184], successfully encoded for this RTP media stream. This is a subset of 764 // FramesEncoded. FramesEncoded - KeyFramesEncoded gives you the number of delta frames encoded. 765 // Does not exist for audio. 766 KeyFramesEncoded uint32 `json:"keyFramesEncoded"` 767 768 // TotalEncodeTime is the total number of seconds that has been spent encoding the 769 // framesEncoded frames of this stream. The average encode time can be calculated by 770 // dividing this value with FramesEncoded. The time it takes to encode one frame is the 771 // time passed between feeding the encoder a frame and the encoder returning encoded data 772 // for that frame. This does not include any additional time it may take to packetize the resulting data. 773 TotalEncodeTime float64 `json:"totalEncodeTime"` 774 775 // TotalPacketSendDelay is the total number of seconds that packets have spent buffered 776 // locally before being transmitted onto the network. The time is measured from when 777 // a packet is emitted from the RTP packetizer until it is handed over to the OS network socket. 778 // This measurement is added to totalPacketSendDelay when packetsSent is incremented. 779 TotalPacketSendDelay float64 `json:"totalPacketSendDelay"` 780 781 // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP 782 // packets. This is calculated by the sending endpoint when sending compound RTCP reports. 783 // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet with the CNAME item. 784 AverageRTCPInterval float64 `json:"averageRtcpInterval"` 785 786 // QualityLimitationReason is the current reason for limiting the resolution and/or framerate, 787 // or "none" if not limited. Only valid for video. 788 QualityLimitationReason QualityLimitationReason `json:"qualityLimitationReason"` 789 790 // QualityLimitationDurations is record of the total time, in seconds, that this 791 // stream has spent in each quality limitation state. The record includes a mapping 792 // for all QualityLimitationReason types, including "none". Only valid for video. 793 QualityLimitationDurations map[string]float64 `json:"qualityLimitationDurations"` 794 795 // QualityLimitationResolutionChanges is the number of times that the resolution has changed 796 // because we are quality limited (qualityLimitationReason has a value other than "none"). 797 // The counter is initially zero and increases when the resolution goes up or down. 798 // For example, if a 720p track is sent as 480p for some time and then recovers to 720p, 799 // qualityLimitationResolutionChanges will have the value 2. Does not exist for audio. 800 QualityLimitationResolutionChanges uint32 `json:"qualityLimitationResolutionChanges"` 801 802 // PerDSCPPacketsSent is the total number of packets sent for this SSRC, per DSCP. 803 // DSCPs are identified as decimal integers in string form. 804 PerDSCPPacketsSent map[string]uint32 `json:"perDscpPacketsSent"` 805 806 // Active indicates whether this RTP stream is configured to be sent or disabled. Note that an 807 // active stream can still not be sending, e.g. when being limited by network conditions. 808 Active bool `json:"active"` 809 } 810 811 func (s OutboundRTPStreamStats) statsMarker() {} 812 813 func unmarshalOutboundRTPStreamStats(b []byte) (OutboundRTPStreamStats, error) { 814 var outboundRTPStreamStats OutboundRTPStreamStats 815 err := json.Unmarshal(b, &outboundRTPStreamStats) 816 if err != nil { 817 return OutboundRTPStreamStats{}, fmt.Errorf("unmarshal outbound rtp stream stats: %w", err) 818 } 819 return outboundRTPStreamStats, nil 820 } 821 822 // RemoteInboundRTPStreamStats contains statistics for the remote endpoint's inbound 823 // RTP stream corresponding to an outbound stream that is currently sent with this 824 // PeerConnection object. It is measured at the remote endpoint and reported in an RTCP 825 // Receiver Report (RR) or RTCP Extended Report (XR). 826 type RemoteInboundRTPStreamStats struct { 827 // Timestamp is the timestamp associated with this object. 828 Timestamp StatsTimestamp `json:"timestamp"` 829 830 // Type is the object's StatsType 831 Type StatsType `json:"type"` 832 833 // ID is a unique id that is associated with the component inspected to produce 834 // this Stats object. Two Stats objects will have the same ID if they were produced 835 // by inspecting the same underlying object. 836 ID string `json:"id"` 837 838 // SSRC is the 32-bit unsigned integer value used to identify the source of the 839 // stream of RTP packets that this stats object concerns. 840 SSRC SSRC `json:"ssrc"` 841 842 // Kind is either "audio" or "video" 843 Kind string `json:"kind"` 844 845 // It is a unique identifier that is associated to the object that was inspected 846 // to produce the TransportStats associated with this RTP stream. 847 TransportID string `json:"transportId"` 848 849 // CodecID is a unique identifier that is associated to the object that was inspected 850 // to produce the CodecStats associated with this RTP stream. 851 CodecID string `json:"codecId"` 852 853 // FIRCount counts the total number of Full Intra Request (FIR) packets received 854 // by the sender. This metric is only valid for video and is sent by receiver. 855 FIRCount uint32 `json:"firCount"` 856 857 // PLICount counts the total number of Picture Loss Indication (PLI) packets 858 // received by the sender. This metric is only valid for video and is sent by receiver. 859 PLICount uint32 `json:"pliCount"` 860 861 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 862 // received by the sender and is sent by receiver. 863 NACKCount uint32 `json:"nackCount"` 864 865 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 866 // by the sender. This metric is only valid for video and is sent by receiver. 867 SLICount uint32 `json:"sliCount"` 868 869 // QPSum is the sum of the QP values of frames passed. The count of frames is 870 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 871 QPSum uint64 `json:"qpSum"` 872 873 // PacketsReceived is the total number of RTP packets received for this SSRC. 874 PacketsReceived uint32 `json:"packetsReceived"` 875 876 // PacketsLost is the total number of RTP packets lost for this SSRC. Note that 877 // because of how this is estimated, it can be negative if more packets are received than sent. 878 PacketsLost int32 `json:"packetsLost"` 879 880 // Jitter is the packet jitter measured in seconds for this SSRC 881 Jitter float64 `json:"jitter"` 882 883 // PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter 884 // buffer due to late or early-arrival, i.e., these packets are not played out. 885 // RTP packets discarded due to packet duplication are not reported in this metric. 886 PacketsDiscarded uint32 `json:"packetsDiscarded"` 887 888 // PacketsRepaired is the cumulative number of lost RTP packets repaired after applying 889 // an error-resilience mechanism. It is measured for the primary source RTP packets 890 // and only counted for RTP packets that have no further chance of repair. 891 PacketsRepaired uint32 `json:"packetsRepaired"` 892 893 // BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts. 894 BurstPacketsLost uint32 `json:"burstPacketsLost"` 895 896 // BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts. 897 BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"` 898 899 // BurstLossCount is the cumulative number of bursts of lost RTP packets. 900 BurstLossCount uint32 `json:"burstLossCount"` 901 902 // BurstDiscardCount is the cumulative number of bursts of discarded RTP packets. 903 BurstDiscardCount uint32 `json:"burstDiscardCount"` 904 905 // BurstLossRate is the fraction of RTP packets lost during bursts to the 906 // total number of RTP packets expected in the bursts. 907 BurstLossRate float64 `json:"burstLossRate"` 908 909 // BurstDiscardRate is the fraction of RTP packets discarded during bursts to 910 // the total number of RTP packets expected in bursts. 911 BurstDiscardRate float64 `json:"burstDiscardRate"` 912 913 // GapLossRate is the fraction of RTP packets lost during the gap periods. 914 GapLossRate float64 `json:"gapLossRate"` 915 916 // GapDiscardRate is the fraction of RTP packets discarded during the gap periods. 917 GapDiscardRate float64 `json:"gapDiscardRate"` 918 919 // LocalID is used for looking up the local OutboundRTPStreamStats object for the same SSRC. 920 LocalID string `json:"localId"` 921 922 // RoundTripTime is the estimated round trip time for this SSRC based on the 923 // RTCP timestamps in the RTCP Receiver Report (RR) and measured in seconds. 924 RoundTripTime float64 `json:"roundTripTime"` 925 926 // TotalRoundTripTime represents the cumulative sum of all round trip time measurements 927 // in seconds since the beginning of the session. The individual round trip time is calculated 928 // based on the RTCP timestamps in the RTCP Receiver Report (RR) [RFC3550], hence requires 929 // a DLSR value other than 0. The average round trip time can be computed from 930 // TotalRoundTripTime by dividing it by RoundTripTimeMeasurements. 931 TotalRoundTripTime float64 `json:"totalRoundTripTime"` 932 933 // FractionLost is the fraction packet loss reported for this SSRC. 934 FractionLost float64 `json:"fractionLost"` 935 936 // RoundTripTimeMeasurements represents the total number of RTCP RR blocks received for this SSRC 937 // that contain a valid round trip time. This counter will not increment if the RoundTripTime can 938 // not be calculated because no RTCP Receiver Report with a DLSR value other than 0 has been received. 939 RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"` 940 } 941 942 func (s RemoteInboundRTPStreamStats) statsMarker() {} 943 944 func unmarshalRemoteInboundRTPStreamStats(b []byte) (RemoteInboundRTPStreamStats, error) { 945 var remoteInboundRTPStreamStats RemoteInboundRTPStreamStats 946 err := json.Unmarshal(b, &remoteInboundRTPStreamStats) 947 if err != nil { 948 return RemoteInboundRTPStreamStats{}, fmt.Errorf("unmarshal remote inbound rtp stream stats: %w", err) 949 } 950 return remoteInboundRTPStreamStats, nil 951 } 952 953 // RemoteOutboundRTPStreamStats contains statistics for the remote endpoint's outbound 954 // RTP stream corresponding to an inbound stream that is currently received with this 955 // PeerConnection object. It is measured at the remote endpoint and reported in an 956 // RTCP Sender Report (SR). 957 type RemoteOutboundRTPStreamStats struct { 958 // Timestamp is the timestamp associated with this object. 959 Timestamp StatsTimestamp `json:"timestamp"` 960 961 // Type is the object's StatsType 962 Type StatsType `json:"type"` 963 964 // ID is a unique id that is associated with the component inspected to produce 965 // this Stats object. Two Stats objects will have the same ID if they were produced 966 // by inspecting the same underlying object. 967 ID string `json:"id"` 968 969 // SSRC is the 32-bit unsigned integer value used to identify the source of the 970 // stream of RTP packets that this stats object concerns. 971 SSRC SSRC `json:"ssrc"` 972 973 // Kind is either "audio" or "video" 974 Kind string `json:"kind"` 975 976 // It is a unique identifier that is associated to the object that was inspected 977 // to produce the TransportStats associated with this RTP stream. 978 TransportID string `json:"transportId"` 979 980 // CodecID is a unique identifier that is associated to the object that was inspected 981 // to produce the CodecStats associated with this RTP stream. 982 CodecID string `json:"codecId"` 983 984 // FIRCount counts the total number of Full Intra Request (FIR) packets received 985 // by the sender. This metric is only valid for video and is sent by receiver. 986 FIRCount uint32 `json:"firCount"` 987 988 // PLICount counts the total number of Picture Loss Indication (PLI) packets 989 // received by the sender. This metric is only valid for video and is sent by receiver. 990 PLICount uint32 `json:"pliCount"` 991 992 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 993 // received by the sender and is sent by receiver. 994 NACKCount uint32 `json:"nackCount"` 995 996 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 997 // by the sender. This metric is only valid for video and is sent by receiver. 998 SLICount uint32 `json:"sliCount"` 999 1000 // QPSum is the sum of the QP values of frames passed. The count of frames is 1001 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 1002 QPSum uint64 `json:"qpSum"` 1003 1004 // PacketsSent is the total number of RTP packets sent for this SSRC. 1005 PacketsSent uint32 `json:"packetsSent"` 1006 1007 // PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that 1008 // have been discarded due to socket errors, i.e. a socket error occurred when handing 1009 // the packets to the socket. This might happen due to various reasons, including 1010 // full buffer or no available memory. 1011 PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` 1012 1013 // FECPacketsSent is the total number of RTP FEC packets sent for this SSRC. 1014 // This counter can also be incremented when sending FEC packets in-band with 1015 // media packets (e.g., with Opus). 1016 FECPacketsSent uint32 `json:"fecPacketsSent"` 1017 1018 // BytesSent is the total number of bytes sent for this SSRC. 1019 BytesSent uint64 `json:"bytesSent"` 1020 1021 // BytesDiscardedOnSend is the total number of bytes for this SSRC that have 1022 // been discarded due to socket errors, i.e. a socket error occurred when handing 1023 // the packets containing the bytes to the socket. This might happen due to various 1024 // reasons, including full buffer or no available memory. 1025 BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"` 1026 1027 // LocalID is used for looking up the local InboundRTPStreamStats object for the same SSRC. 1028 LocalID string `json:"localId"` 1029 1030 // RemoteTimestamp represents the remote timestamp at which these statistics were 1031 // sent by the remote endpoint. This differs from timestamp, which represents the 1032 // time at which the statistics were generated or received by the local endpoint. 1033 // The RemoteTimestamp, if present, is derived from the NTP timestamp in an RTCP 1034 // Sender Report (SR) packet, which reflects the remote endpoint's clock. 1035 // That clock may not be synchronized with the local clock. 1036 RemoteTimestamp StatsTimestamp `json:"remoteTimestamp"` 1037 1038 // ReportsSent represents the total number of RTCP Sender Report (SR) blocks sent for this SSRC. 1039 ReportsSent uint64 `json:"reportsSent"` 1040 1041 // RoundTripTime is estimated round trip time for this SSRC based on the latest 1042 // RTCP Sender Report (SR) that contains a DLRR report block as defined in [RFC3611]. 1043 // The Calculation of the round trip time is defined in section 4.5. of [RFC3611]. 1044 // Does not exist if the latest SR does not contain the DLRR report block, or if the last RR timestamp 1045 // in the DLRR report block is zero, or if the delay since last RR value in the DLRR report block is zero. 1046 RoundTripTime float64 `json:"roundTripTime"` 1047 1048 // TotalRoundTripTime represents the cumulative sum of all round trip time measurements in seconds 1049 // since the beginning of the session. The individual round trip time is calculated based on the DLRR 1050 // report block in the RTCP Sender Report (SR) [RFC3611]. This counter will not increment if the 1051 // RoundTripTime can not be calculated. The average round trip time can be computed from 1052 // TotalRoundTripTime by dividing it by RoundTripTimeMeasurements. 1053 TotalRoundTripTime float64 `json:"totalRoundTripTime"` 1054 1055 // RoundTripTimeMeasurements represents the total number of RTCP Sender Report (SR) blocks 1056 // received for this SSRC that contain a DLRR report block that can derive a valid round trip time 1057 // according to [RFC3611]. This counter will not increment if the RoundTripTime can not be calculated. 1058 RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"` 1059 } 1060 1061 func (s RemoteOutboundRTPStreamStats) statsMarker() {} 1062 1063 func unmarshalRemoteOutboundRTPStreamStats(b []byte) (RemoteOutboundRTPStreamStats, error) { 1064 var remoteOutboundRTPStreamStats RemoteOutboundRTPStreamStats 1065 err := json.Unmarshal(b, &remoteOutboundRTPStreamStats) 1066 if err != nil { 1067 return RemoteOutboundRTPStreamStats{}, fmt.Errorf("unmarshal remote outbound rtp stream stats: %w", err) 1068 } 1069 return remoteOutboundRTPStreamStats, nil 1070 } 1071 1072 // RTPContributingSourceStats contains statistics for a contributing source (CSRC) that contributed 1073 // to an inbound RTP stream. 1074 type RTPContributingSourceStats struct { 1075 // Timestamp is the timestamp associated with this object. 1076 Timestamp StatsTimestamp `json:"timestamp"` 1077 1078 // Type is the object's StatsType 1079 Type StatsType `json:"type"` 1080 1081 // ID is a unique id that is associated with the component inspected to produce 1082 // this Stats object. Two Stats objects will have the same ID if they were produced 1083 // by inspecting the same underlying object. 1084 ID string `json:"id"` 1085 1086 // ContributorSSRC is the SSRC identifier of the contributing source represented 1087 // by this stats object. It is a 32-bit unsigned integer that appears in the CSRC 1088 // list of any packets the relevant source contributed to. 1089 ContributorSSRC SSRC `json:"contributorSsrc"` 1090 1091 // InboundRTPStreamID is the ID of the InboundRTPStreamStats object representing 1092 // the inbound RTP stream that this contributing source is contributing to. 1093 InboundRTPStreamID string `json:"inboundRtpStreamId"` 1094 1095 // PacketsContributedTo is the total number of RTP packets that this contributing 1096 // source contributed to. This value is incremented each time a packet is counted 1097 // by InboundRTPStreamStats.packetsReceived, and the packet's CSRC list contains 1098 // the SSRC identifier of this contributing source, ContributorSSRC. 1099 PacketsContributedTo uint32 `json:"packetsContributedTo"` 1100 1101 // AudioLevel is present if the last received RTP packet that this source contributed 1102 // to contained an [RFC6465] mixer-to-client audio level header extension. The value 1103 // of audioLevel is between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents 1104 // silence, and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov. 1105 AudioLevel float64 `json:"audioLevel"` 1106 } 1107 1108 func (s RTPContributingSourceStats) statsMarker() {} 1109 1110 func unmarshalCSRCStats(b []byte) (RTPContributingSourceStats, error) { 1111 var csrcStats RTPContributingSourceStats 1112 err := json.Unmarshal(b, &csrcStats) 1113 if err != nil { 1114 return RTPContributingSourceStats{}, fmt.Errorf("unmarshal csrc stats: %w", err) 1115 } 1116 return csrcStats, nil 1117 } 1118 1119 // AudioSourceStats represents an audio track that is attached to one or more senders. 1120 type AudioSourceStats struct { 1121 // Timestamp is the timestamp associated with this object. 1122 Timestamp StatsTimestamp `json:"timestamp"` 1123 1124 // Type is the object's StatsType 1125 Type StatsType `json:"type"` 1126 1127 // ID is a unique id that is associated with the component inspected to produce 1128 // this Stats object. Two Stats objects will have the same ID if they were produced 1129 // by inspecting the same underlying object. 1130 ID string `json:"id"` 1131 1132 // TrackIdentifier represents the id property of the track. 1133 TrackIdentifier string `json:"trackIdentifier"` 1134 1135 // Kind is "audio" 1136 Kind string `json:"kind"` 1137 1138 // AudioLevel represents the output audio level of the track. 1139 // 1140 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 1141 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 1142 // the sound pressure level from 0 dBov. 1143 // 1144 // If the track is sourced from an Receiver, does no audio processing, has a 1145 // constant level, and has a volume setting of 1.0, the audio level is expected 1146 // to be the same as the audio level of the source SSRC, while if the volume setting 1147 // is 0.5, the AudioLevel is expected to be half that value. 1148 AudioLevel float64 `json:"audioLevel"` 1149 1150 // TotalAudioEnergy is the total energy of all the audio samples sent/received 1151 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 1152 // each audio sample seen. 1153 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 1154 1155 // TotalSamplesDuration represents the total duration in seconds of all samples 1156 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1157 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1158 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1159 1160 // EchoReturnLoss is only present while the sender is sending a track sourced from 1161 // a microphone where echo cancellation is applied. Calculated in decibels. 1162 EchoReturnLoss float64 `json:"echoReturnLoss"` 1163 1164 // EchoReturnLossEnhancement is only present while the sender is sending a track 1165 // sourced from a microphone where echo cancellation is applied. Calculated in decibels. 1166 EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"` 1167 1168 // DroppedSamplesDuration represents the total duration, in seconds, of samples produced by the device that got 1169 // dropped before reaching the media source. Only applicable if this media source is backed by an audio capture device. 1170 DroppedSamplesDuration float64 `json:"droppedSamplesDuration"` 1171 1172 // DroppedSamplesEvents is the number of dropped samples events. This counter increases every time a sample is 1173 // dropped after a non-dropped sample. That is, multiple consecutive dropped samples will increase 1174 // droppedSamplesDuration multiple times but is a single dropped samples event. 1175 DroppedSamplesEvents uint64 `json:"droppedSamplesEvents"` 1176 1177 // TotalCaptureDelay is the total delay, in seconds, for each audio sample between the time the sample was emitted 1178 // by the capture device and the sample reaching the source. This can be used together with totalSamplesCaptured to 1179 // calculate the average capture delay per sample. Only applicable if the audio source represents an audio capture device. 1180 TotalCaptureDelay float64 `json:"totalCaptureDelay"` 1181 1182 // TotalSamplesCaptured is the total number of captured samples reaching the audio source, i.e. that were not dropped 1183 // by the capture pipeline. The frequency of the media source is not necessarily the same as the frequency of encoders 1184 // later in the pipeline. Only applicable if the audio source represents an audio capture device. 1185 TotalSamplesCaptured uint64 `json:"totalSamplesCaptured"` 1186 } 1187 1188 func (s AudioSourceStats) statsMarker() {} 1189 1190 // VideoSourceStats represents a video track that is attached to one or more senders. 1191 type VideoSourceStats struct { 1192 // Timestamp is the timestamp associated with this object. 1193 Timestamp StatsTimestamp `json:"timestamp"` 1194 1195 // Type is the object's StatsType 1196 Type StatsType `json:"type"` 1197 1198 // ID is a unique id that is associated with the component inspected to produce 1199 // this Stats object. Two Stats objects will have the same ID if they were produced 1200 // by inspecting the same underlying object. 1201 ID string `json:"id"` 1202 1203 // TrackIdentifier represents the id property of the track. 1204 TrackIdentifier string `json:"trackIdentifier"` 1205 1206 // Kind is "video" 1207 Kind string `json:"kind"` 1208 1209 // Width is width of the last frame originating from this source in pixels. 1210 Width uint32 `json:"width"` 1211 1212 // Height is height of the last frame originating from this source in pixels. 1213 Height uint32 `json:"height"` 1214 1215 // Frames is the total number of frames originating from this source. 1216 Frames uint32 `json:"frames"` 1217 1218 // FramesPerSecond is the number of frames originating from this source, measured during the last second. 1219 FramesPerSecond float64 `json:"framesPerSecond"` 1220 } 1221 1222 func (s VideoSourceStats) statsMarker() {} 1223 1224 func unmarshalMediaSourceStats(b []byte) (Stats, error) { 1225 type kindJSON struct { 1226 Kind string `json:"kind"` 1227 } 1228 kindHolder := kindJSON{} 1229 1230 err := json.Unmarshal(b, &kindHolder) 1231 if err != nil { 1232 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1233 } 1234 1235 switch MediaKind(kindHolder.Kind) { 1236 case MediaKindAudio: 1237 var mediaSourceStats AudioSourceStats 1238 err := json.Unmarshal(b, &mediaSourceStats) 1239 if err != nil { 1240 return nil, fmt.Errorf("unmarshal audio source stats: %w", err) 1241 } 1242 return mediaSourceStats, nil 1243 case MediaKindVideo: 1244 var mediaSourceStats VideoSourceStats 1245 err := json.Unmarshal(b, &mediaSourceStats) 1246 if err != nil { 1247 return nil, fmt.Errorf("unmarshal video source stats: %w", err) 1248 } 1249 return mediaSourceStats, nil 1250 default: 1251 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1252 } 1253 } 1254 1255 // AudioPlayoutStats represents one playout path - if the same playout stats object is referenced by multiple 1256 // RTCInboundRtpStreamStats this is an indication that audio mixing is happening in which case sample counters in this 1257 // stats object refer to the samples after mixing. Only applicable if the playout path represents an audio device. 1258 type AudioPlayoutStats struct { 1259 // Timestamp is the timestamp associated with this object. 1260 Timestamp StatsTimestamp `json:"timestamp"` 1261 1262 // Type is the object's StatsType 1263 Type StatsType `json:"type"` 1264 1265 // ID is a unique id that is associated with the component inspected to produce 1266 // this Stats object. Two Stats objects will have the same ID if they were produced 1267 // by inspecting the same underlying object. 1268 ID string `json:"id"` 1269 1270 // Kind is "audio" 1271 Kind string `json:"kind"` 1272 1273 // SynthesizedSamplesDuration is measured in seconds and is incremented each time an audio sample is synthesized by 1274 // this playout path. This metric can be used together with totalSamplesDuration to calculate the percentage of played 1275 // out media being synthesized. If the playout path is unable to produce audio samples on time for device playout, 1276 // samples are synthesized to be playout out instead. Synthesization typically only happens if the pipeline is 1277 // underperforming. Samples synthesized by the RTCInboundRtpStreamStats are not counted for here, but in 1278 // InboundRtpStreamStats.concealedSamples. 1279 SynthesizedSamplesDuration float64 `json:"synthesizedSamplesDuration"` 1280 1281 // SynthesizedSamplesEvents is the number of synthesized samples events. This counter increases every time a sample 1282 // is synthesized after a non-synthesized sample. That is, multiple consecutive synthesized samples will increase 1283 // synthesizedSamplesDuration multiple times but is a single synthesization samples event. 1284 SynthesizedSamplesEvents uint64 `json:"synthesizedSamplesEvents"` 1285 1286 // TotalSamplesDuration represents the total duration in seconds of all samples 1287 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1288 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1289 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1290 1291 // When audio samples are pulled by the playout device, this counter is incremented with the estimated delay of the 1292 // playout path for that audio sample. The playout delay includes the delay from being emitted to the actual time of 1293 // playout on the device. This metric can be used together with totalSamplesCount to calculate the average 1294 // playout delay per sample. 1295 TotalPlayoutDelay float64 `json:"totalPlayoutDelay"` 1296 1297 // When audio samples are pulled by the playout device, this counter is incremented with the number of samples 1298 // emitted for playout. 1299 TotalSamplesCount uint64 `json:"totalSamplesCount"` 1300 } 1301 1302 func (s AudioPlayoutStats) statsMarker() {} 1303 1304 func unmarshalMediaPlayoutStats(b []byte) (Stats, error) { 1305 var audioPlayoutStats AudioPlayoutStats 1306 err := json.Unmarshal(b, &audioPlayoutStats) 1307 if err != nil { 1308 return nil, fmt.Errorf("unmarshal audio playout stats: %w", err) 1309 } 1310 return audioPlayoutStats, nil 1311 } 1312 1313 // PeerConnectionStats contains statistics related to the PeerConnection object. 1314 type PeerConnectionStats struct { 1315 // Timestamp is the timestamp associated with this object. 1316 Timestamp StatsTimestamp `json:"timestamp"` 1317 1318 // Type is the object's StatsType 1319 Type StatsType `json:"type"` 1320 1321 // ID is a unique id that is associated with the component inspected to produce 1322 // this Stats object. Two Stats objects will have the same ID if they were produced 1323 // by inspecting the same underlying object. 1324 ID string `json:"id"` 1325 1326 // DataChannelsOpened represents the number of unique DataChannels that have 1327 // entered the "open" state during their lifetime. 1328 DataChannelsOpened uint32 `json:"dataChannelsOpened"` 1329 1330 // DataChannelsClosed represents the number of unique DataChannels that have 1331 // left the "open" state during their lifetime (due to being closed by either 1332 // end or the underlying transport being closed). DataChannels that transition 1333 // from "connecting" to "closing" or "closed" without ever being "open" 1334 // are not counted in this number. 1335 DataChannelsClosed uint32 `json:"dataChannelsClosed"` 1336 1337 // DataChannelsRequested Represents the number of unique DataChannels returned 1338 // from a successful createDataChannel() call on the PeerConnection. If the 1339 // underlying data transport is not established, these may be in the "connecting" state. 1340 DataChannelsRequested uint32 `json:"dataChannelsRequested"` 1341 1342 // DataChannelsAccepted represents the number of unique DataChannels signaled 1343 // in a "datachannel" event on the PeerConnection. 1344 DataChannelsAccepted uint32 `json:"dataChannelsAccepted"` 1345 } 1346 1347 func (s PeerConnectionStats) statsMarker() {} 1348 1349 func unmarshalPeerConnectionStats(b []byte) (PeerConnectionStats, error) { 1350 var pcStats PeerConnectionStats 1351 err := json.Unmarshal(b, &pcStats) 1352 if err != nil { 1353 return PeerConnectionStats{}, fmt.Errorf("unmarshal pc stats: %w", err) 1354 } 1355 return pcStats, nil 1356 } 1357 1358 // DataChannelStats contains statistics related to each DataChannel ID. 1359 type DataChannelStats struct { 1360 // Timestamp is the timestamp associated with this object. 1361 Timestamp StatsTimestamp `json:"timestamp"` 1362 1363 // Type is the object's StatsType 1364 Type StatsType `json:"type"` 1365 1366 // ID is a unique id that is associated with the component inspected to produce 1367 // this Stats object. Two Stats objects will have the same ID if they were produced 1368 // by inspecting the same underlying object. 1369 ID string `json:"id"` 1370 1371 // Label is the "label" value of the DataChannel object. 1372 Label string `json:"label"` 1373 1374 // Protocol is the "protocol" value of the DataChannel object. 1375 Protocol string `json:"protocol"` 1376 1377 // DataChannelIdentifier is the "id" attribute of the DataChannel object. 1378 DataChannelIdentifier int32 `json:"dataChannelIdentifier"` 1379 1380 // TransportID the ID of the TransportStats object for transport used to carry this datachannel. 1381 TransportID string `json:"transportId"` 1382 1383 // State is the "readyState" value of the DataChannel object. 1384 State DataChannelState `json:"state"` 1385 1386 // MessagesSent represents the total number of API "message" events sent. 1387 MessagesSent uint32 `json:"messagesSent"` 1388 1389 // BytesSent represents the total number of payload bytes sent on this 1390 // datachannel not including headers or padding. 1391 BytesSent uint64 `json:"bytesSent"` 1392 1393 // MessagesReceived represents the total number of API "message" events received. 1394 MessagesReceived uint32 `json:"messagesReceived"` 1395 1396 // BytesReceived represents the total number of bytes received on this 1397 // datachannel not including headers or padding. 1398 BytesReceived uint64 `json:"bytesReceived"` 1399 } 1400 1401 func (s DataChannelStats) statsMarker() {} 1402 1403 func unmarshalDataChannelStats(b []byte) (DataChannelStats, error) { 1404 var dataChannelStats DataChannelStats 1405 err := json.Unmarshal(b, &dataChannelStats) 1406 if err != nil { 1407 return DataChannelStats{}, fmt.Errorf("unmarshal data channel stats: %w", err) 1408 } 1409 return dataChannelStats, nil 1410 } 1411 1412 // MediaStreamStats contains statistics related to a specific MediaStream. 1413 type MediaStreamStats struct { 1414 // Timestamp is the timestamp associated with this object. 1415 Timestamp StatsTimestamp `json:"timestamp"` 1416 1417 // Type is the object's StatsType 1418 Type StatsType `json:"type"` 1419 1420 // ID is a unique id that is associated with the component inspected to produce 1421 // this Stats object. Two Stats objects will have the same ID if they were produced 1422 // by inspecting the same underlying object. 1423 ID string `json:"id"` 1424 1425 // StreamIdentifier is the "id" property of the MediaStream 1426 StreamIdentifier string `json:"streamIdentifier"` 1427 1428 // TrackIDs is a list of the identifiers of the stats object representing the 1429 // stream's tracks, either ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats. 1430 TrackIDs []string `json:"trackIds"` 1431 } 1432 1433 func (s MediaStreamStats) statsMarker() {} 1434 1435 func unmarshalStreamStats(b []byte) (MediaStreamStats, error) { 1436 var streamStats MediaStreamStats 1437 err := json.Unmarshal(b, &streamStats) 1438 if err != nil { 1439 return MediaStreamStats{}, fmt.Errorf("unmarshal stream stats: %w", err) 1440 } 1441 return streamStats, nil 1442 } 1443 1444 // AudioSenderStats represents the stats about one audio sender of a PeerConnection 1445 // object for which one calls GetStats. 1446 // 1447 // It appears in the stats as soon as the RTPSender is added by either AddTrack 1448 // or AddTransceiver, or by media negotiation. 1449 type AudioSenderStats struct { 1450 // Timestamp is the timestamp associated with this object. 1451 Timestamp StatsTimestamp `json:"timestamp"` 1452 1453 // Type is the object's StatsType 1454 Type StatsType `json:"type"` 1455 1456 // ID is a unique id that is associated with the component inspected to produce 1457 // this Stats object. Two Stats objects will have the same ID if they were produced 1458 // by inspecting the same underlying object. 1459 ID string `json:"id"` 1460 1461 // TrackIdentifier represents the id property of the track. 1462 TrackIdentifier string `json:"trackIdentifier"` 1463 1464 // RemoteSource is true if the source is remote, for instance if it is sourced 1465 // from another host via a PeerConnection. False otherwise. Only applicable for 'track' stats. 1466 RemoteSource bool `json:"remoteSource"` 1467 1468 // Ended reflects the "ended" state of the track. 1469 Ended bool `json:"ended"` 1470 1471 // Kind is "audio" 1472 Kind string `json:"kind"` 1473 1474 // AudioLevel represents the output audio level of the track. 1475 // 1476 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 1477 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 1478 // the sound pressure level from 0 dBov. 1479 // 1480 // If the track is sourced from an Receiver, does no audio processing, has a 1481 // constant level, and has a volume setting of 1.0, the audio level is expected 1482 // to be the same as the audio level of the source SSRC, while if the volume setting 1483 // is 0.5, the AudioLevel is expected to be half that value. 1484 // 1485 // For outgoing audio tracks, the AudioLevel is the level of the audio being sent. 1486 AudioLevel float64 `json:"audioLevel"` 1487 1488 // TotalAudioEnergy is the total energy of all the audio samples sent/received 1489 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 1490 // each audio sample seen. 1491 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 1492 1493 // VoiceActivityFlag represents whether the last RTP packet sent or played out 1494 // by this track contained voice activity or not based on the presence of the 1495 // V bit in the extension header, as defined in [RFC6464]. 1496 // 1497 // This value indicates the voice activity in the latest RTP packet played out 1498 // from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag. 1499 VoiceActivityFlag bool `json:"voiceActivityFlag"` 1500 1501 // TotalSamplesDuration represents the total duration in seconds of all samples 1502 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1503 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1504 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1505 1506 // EchoReturnLoss is only present while the sender is sending a track sourced from 1507 // a microphone where echo cancellation is applied. Calculated in decibels. 1508 EchoReturnLoss float64 `json:"echoReturnLoss"` 1509 1510 // EchoReturnLossEnhancement is only present while the sender is sending a track 1511 // sourced from a microphone where echo cancellation is applied. Calculated in decibels. 1512 EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"` 1513 1514 // TotalSamplesSent is the total number of samples that have been sent by this sender. 1515 TotalSamplesSent uint64 `json:"totalSamplesSent"` 1516 } 1517 1518 func (s AudioSenderStats) statsMarker() {} 1519 1520 // SenderAudioTrackAttachmentStats object represents the stats about one attachment 1521 // of an audio MediaStreamTrack to the PeerConnection object for which one calls GetStats. 1522 // 1523 // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver, 1524 // via ReplaceTrack on an RTPSender object). 1525 // 1526 // If an audio track is attached twice (via AddTransceiver or ReplaceTrack), there 1527 // will be two SenderAudioTrackAttachmentStats objects, one for each attachment. 1528 // They will have the same "TrackIdentifier" attribute, but different "ID" attributes. 1529 // 1530 // If the track is detached from the PeerConnection (via removeTrack or via replaceTrack), 1531 // it continues to appear, but with the "ObjectDeleted" member set to true. 1532 type SenderAudioTrackAttachmentStats AudioSenderStats 1533 1534 func (s SenderAudioTrackAttachmentStats) statsMarker() {} 1535 1536 // VideoSenderStats represents the stats about one video sender of a PeerConnection 1537 // object for which one calls GetStats. 1538 // 1539 // It appears in the stats as soon as the sender is added by either AddTrack or 1540 // AddTransceiver, or by media negotiation. 1541 type VideoSenderStats struct { 1542 // Timestamp is the timestamp associated with this object. 1543 Timestamp StatsTimestamp `json:"timestamp"` 1544 1545 // Type is the object's StatsType 1546 Type StatsType `json:"type"` 1547 1548 // ID is a unique id that is associated with the component inspected to produce 1549 // this Stats object. Two Stats objects will have the same ID if they were produced 1550 // by inspecting the same underlying object. 1551 ID string `json:"id"` 1552 1553 // Kind is "video" 1554 Kind string `json:"kind"` 1555 1556 // FramesCaptured represents the total number of frames captured, before encoding, 1557 // for this RTPSender (or for this MediaStreamTrack, if type is "track"). For example, 1558 // if type is "sender" and this sender's track represents a camera, then this is the 1559 // number of frames produced by the camera for this track while being sent by this sender, 1560 // combined with the number of frames produced by all tracks previously attached to this 1561 // sender while being sent by this sender. Framerates can vary due to hardware limitations 1562 // or environmental factors such as lighting conditions. 1563 FramesCaptured uint32 `json:"framesCaptured"` 1564 1565 // FramesSent represents the total number of frames sent by this RTPSender 1566 // (or for this MediaStreamTrack, if type is "track"). 1567 FramesSent uint32 `json:"framesSent"` 1568 1569 // HugeFramesSent represents the total number of huge frames sent by this RTPSender 1570 // (or for this MediaStreamTrack, if type is "track"). Huge frames, by definition, 1571 // are frames that have an encoded size at least 2.5 times the average size of the frames. 1572 // The average size of the frames is defined as the target bitrate per second divided 1573 // by the target fps at the time the frame was encoded. These are usually complex 1574 // to encode frames with a lot of changes in the picture. This can be used to estimate, 1575 // e.g slide changes in the streamed presentation. If a huge frame is also a key frame, 1576 // then both counters HugeFramesSent and KeyFramesSent are incremented. 1577 HugeFramesSent uint32 `json:"hugeFramesSent"` 1578 1579 // KeyFramesSent represents the total number of key frames sent by this RTPSender 1580 // (or for this MediaStreamTrack, if type is "track"), such as Infra-frames in 1581 // VP8 [RFC6386] or I-frames in H.264 [RFC6184]. This is a subset of FramesSent. 1582 // FramesSent - KeyFramesSent gives you the number of delta frames sent. 1583 KeyFramesSent uint32 `json:"keyFramesSent"` 1584 } 1585 1586 func (s VideoSenderStats) statsMarker() {} 1587 1588 // SenderVideoTrackAttachmentStats represents the stats about one attachment of a 1589 // video MediaStreamTrack to the PeerConnection object for which one calls GetStats. 1590 // 1591 // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver, 1592 // via ReplaceTrack on an RTPSender object). 1593 // 1594 // If a video track is attached twice (via AddTransceiver or ReplaceTrack), there 1595 // will be two SenderVideoTrackAttachmentStats objects, one for each attachment. 1596 // They will have the same "TrackIdentifier" attribute, but different "ID" attributes. 1597 // 1598 // If the track is detached from the PeerConnection (via RemoveTrack or via ReplaceTrack), 1599 // it continues to appear, but with the "ObjectDeleted" member set to true. 1600 type SenderVideoTrackAttachmentStats VideoSenderStats 1601 1602 func (s SenderVideoTrackAttachmentStats) statsMarker() {} 1603 1604 func unmarshalSenderStats(b []byte) (Stats, error) { 1605 type kindJSON struct { 1606 Kind string `json:"kind"` 1607 } 1608 kindHolder := kindJSON{} 1609 1610 err := json.Unmarshal(b, &kindHolder) 1611 if err != nil { 1612 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1613 } 1614 1615 switch MediaKind(kindHolder.Kind) { 1616 case MediaKindAudio: 1617 var senderStats AudioSenderStats 1618 err := json.Unmarshal(b, &senderStats) 1619 if err != nil { 1620 return nil, fmt.Errorf("unmarshal audio sender stats: %w", err) 1621 } 1622 return senderStats, nil 1623 case MediaKindVideo: 1624 var senderStats VideoSenderStats 1625 err := json.Unmarshal(b, &senderStats) 1626 if err != nil { 1627 return nil, fmt.Errorf("unmarshal video sender stats: %w", err) 1628 } 1629 return senderStats, nil 1630 default: 1631 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1632 } 1633 } 1634 1635 func unmarshalTrackStats(b []byte) (Stats, error) { 1636 type kindJSON struct { 1637 Kind string `json:"kind"` 1638 } 1639 kindHolder := kindJSON{} 1640 1641 err := json.Unmarshal(b, &kindHolder) 1642 if err != nil { 1643 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1644 } 1645 1646 switch MediaKind(kindHolder.Kind) { 1647 case MediaKindAudio: 1648 var trackStats SenderAudioTrackAttachmentStats 1649 err := json.Unmarshal(b, &trackStats) 1650 if err != nil { 1651 return nil, fmt.Errorf("unmarshal audio track stats: %w", err) 1652 } 1653 return trackStats, nil 1654 case MediaKindVideo: 1655 var trackStats SenderVideoTrackAttachmentStats 1656 err := json.Unmarshal(b, &trackStats) 1657 if err != nil { 1658 return nil, fmt.Errorf("unmarshal video track stats: %w", err) 1659 } 1660 return trackStats, nil 1661 default: 1662 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1663 } 1664 } 1665 1666 // AudioReceiverStats contains audio metrics related to a specific receiver. 1667 type AudioReceiverStats struct { 1668 // Timestamp is the timestamp associated with this object. 1669 Timestamp StatsTimestamp `json:"timestamp"` 1670 1671 // Type is the object's StatsType 1672 Type StatsType `json:"type"` 1673 1674 // ID is a unique id that is associated with the component inspected to produce 1675 // this Stats object. Two Stats objects will have the same ID if they were produced 1676 // by inspecting the same underlying object. 1677 ID string `json:"id"` 1678 1679 // Kind is "audio" 1680 Kind string `json:"kind"` 1681 1682 // AudioLevel represents the output audio level of the track. 1683 // 1684 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 1685 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 1686 // the sound pressure level from 0 dBov. 1687 // 1688 // If the track is sourced from an Receiver, does no audio processing, has a 1689 // constant level, and has a volume setting of 1.0, the audio level is expected 1690 // to be the same as the audio level of the source SSRC, while if the volume setting 1691 // is 0.5, the AudioLevel is expected to be half that value. 1692 // 1693 // For outgoing audio tracks, the AudioLevel is the level of the audio being sent. 1694 AudioLevel float64 `json:"audioLevel"` 1695 1696 // TotalAudioEnergy is the total energy of all the audio samples sent/received 1697 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 1698 // each audio sample seen. 1699 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 1700 1701 // VoiceActivityFlag represents whether the last RTP packet sent or played out 1702 // by this track contained voice activity or not based on the presence of the 1703 // V bit in the extension header, as defined in [RFC6464]. 1704 // 1705 // This value indicates the voice activity in the latest RTP packet played out 1706 // from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag. 1707 VoiceActivityFlag bool `json:"voiceActivityFlag"` 1708 1709 // TotalSamplesDuration represents the total duration in seconds of all samples 1710 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1711 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1712 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1713 1714 // EstimatedPlayoutTimestamp is the estimated playout time of this receiver's 1715 // track. The playout time is the NTP timestamp of the last playable sample that 1716 // has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP 1717 // timestamps), extrapolated with the time elapsed since it was ready to be played out. 1718 // This is the "current time" of the track in NTP clock time of the sender and 1719 // can be present even if there is no audio currently playing. 1720 // 1721 // This can be useful for estimating how much audio and video is out of 1722 // sync for two tracks from the same source: 1723 // AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp 1724 EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"` 1725 1726 // JitterBufferDelay is the sum of the time, in seconds, each sample takes from 1727 // the time it is received and to the time it exits the jitter buffer. 1728 // This increases upon samples exiting, having completed their time in the buffer 1729 // (incrementing JitterBufferEmittedCount). The average jitter buffer delay can 1730 // be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. 1731 JitterBufferDelay float64 `json:"jitterBufferDelay"` 1732 1733 // JitterBufferEmittedCount is the total number of samples that have come out 1734 // of the jitter buffer (increasing JitterBufferDelay). 1735 JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` 1736 1737 // TotalSamplesReceived is the total number of samples that have been received 1738 // by this receiver. This includes ConcealedSamples. 1739 TotalSamplesReceived uint64 `json:"totalSamplesReceived"` 1740 1741 // ConcealedSamples is the total number of samples that are concealed samples. 1742 // A concealed sample is a sample that is based on data that was synthesized 1743 // to conceal packet loss and does not represent incoming data. 1744 ConcealedSamples uint64 `json:"concealedSamples"` 1745 1746 // ConcealmentEvents is the number of concealment events. This counter increases 1747 // every time a concealed sample is synthesized after a non-concealed sample. 1748 // That is, multiple consecutive concealed samples will increase the concealedSamples 1749 // count multiple times but is a single concealment event. 1750 ConcealmentEvents uint64 `json:"concealmentEvents"` 1751 } 1752 1753 func (s AudioReceiverStats) statsMarker() {} 1754 1755 // VideoReceiverStats contains video metrics related to a specific receiver. 1756 type VideoReceiverStats struct { 1757 // Timestamp is the timestamp associated with this object. 1758 Timestamp StatsTimestamp `json:"timestamp"` 1759 1760 // Type is the object's StatsType 1761 Type StatsType `json:"type"` 1762 1763 // ID is a unique id that is associated with the component inspected to produce 1764 // this Stats object. Two Stats objects will have the same ID if they were produced 1765 // by inspecting the same underlying object. 1766 ID string `json:"id"` 1767 1768 // Kind is "video" 1769 Kind string `json:"kind"` 1770 1771 // FrameWidth represents the width of the last processed frame for this track. 1772 // Before the first frame is processed this attribute is missing. 1773 FrameWidth uint32 `json:"frameWidth"` 1774 1775 // FrameHeight represents the height of the last processed frame for this track. 1776 // Before the first frame is processed this attribute is missing. 1777 FrameHeight uint32 `json:"frameHeight"` 1778 1779 // FramesPerSecond represents the nominal FPS value before the degradation preference 1780 // is applied. It is the number of complete frames in the last second. For sending 1781 // tracks it is the current captured FPS and for the receiving tracks it is the 1782 // current decoding framerate. 1783 FramesPerSecond float64 `json:"framesPerSecond"` 1784 1785 // EstimatedPlayoutTimestamp is the estimated playout time of this receiver's 1786 // track. The playout time is the NTP timestamp of the last playable sample that 1787 // has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP 1788 // timestamps), extrapolated with the time elapsed since it was ready to be played out. 1789 // This is the "current time" of the track in NTP clock time of the sender and 1790 // can be present even if there is no audio currently playing. 1791 // 1792 // This can be useful for estimating how much audio and video is out of 1793 // sync for two tracks from the same source: 1794 // AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp 1795 EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"` 1796 1797 // JitterBufferDelay is the sum of the time, in seconds, each sample takes from 1798 // the time it is received and to the time it exits the jitter buffer. 1799 // This increases upon samples exiting, having completed their time in the buffer 1800 // (incrementing JitterBufferEmittedCount). The average jitter buffer delay can 1801 // be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. 1802 JitterBufferDelay float64 `json:"jitterBufferDelay"` 1803 1804 // JitterBufferEmittedCount is the total number of samples that have come out 1805 // of the jitter buffer (increasing JitterBufferDelay). 1806 JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` 1807 1808 // FramesReceived Represents the total number of complete frames received for 1809 // this receiver. This metric is incremented when the complete frame is received. 1810 FramesReceived uint32 `json:"framesReceived"` 1811 1812 // KeyFramesReceived represents the total number of complete key frames received 1813 // for this MediaStreamTrack, such as Infra-frames in VP8 [RFC6386] or I-frames 1814 // in H.264 [RFC6184]. This is a subset of framesReceived. `framesReceived - keyFramesReceived` 1815 // gives you the number of delta frames received. This metric is incremented when 1816 // the complete key frame is received. It is not incremented if a partial key 1817 // frames is received and sent for decoding, i.e., the frame could not be recovered 1818 // via retransmission or FEC. 1819 KeyFramesReceived uint32 `json:"keyFramesReceived"` 1820 1821 // FramesDecoded represents the total number of frames correctly decoded for this 1822 // SSRC, i.e., frames that would be displayed if no frames are dropped. 1823 FramesDecoded uint32 `json:"framesDecoded"` 1824 1825 // FramesDropped is the total number of frames dropped predecode or dropped 1826 // because the frame missed its display deadline for this receiver's track. 1827 FramesDropped uint32 `json:"framesDropped"` 1828 1829 // The cumulative number of partial frames lost. This metric is incremented when 1830 // the frame is sent to the decoder. If the partial frame is received and recovered 1831 // via retransmission or FEC before decoding, the FramesReceived counter is incremented. 1832 PartialFramesLost uint32 `json:"partialFramesLost"` 1833 1834 // FullFramesLost is the cumulative number of full frames lost. 1835 FullFramesLost uint32 `json:"fullFramesLost"` 1836 } 1837 1838 func (s VideoReceiverStats) statsMarker() {} 1839 1840 func unmarshalReceiverStats(b []byte) (Stats, error) { 1841 type kindJSON struct { 1842 Kind string `json:"kind"` 1843 } 1844 kindHolder := kindJSON{} 1845 1846 err := json.Unmarshal(b, &kindHolder) 1847 if err != nil { 1848 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1849 } 1850 1851 switch MediaKind(kindHolder.Kind) { 1852 case MediaKindAudio: 1853 var receiverStats AudioReceiverStats 1854 err := json.Unmarshal(b, &receiverStats) 1855 if err != nil { 1856 return nil, fmt.Errorf("unmarshal audio receiver stats: %w", err) 1857 } 1858 return receiverStats, nil 1859 case MediaKindVideo: 1860 var receiverStats VideoReceiverStats 1861 err := json.Unmarshal(b, &receiverStats) 1862 if err != nil { 1863 return nil, fmt.Errorf("unmarshal video receiver stats: %w", err) 1864 } 1865 return receiverStats, nil 1866 default: 1867 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1868 } 1869 } 1870 1871 // TransportStats contains transport statistics related to the PeerConnection object. 1872 type TransportStats struct { 1873 // Timestamp is the timestamp associated with this object. 1874 Timestamp StatsTimestamp `json:"timestamp"` 1875 1876 // Type is the object's StatsType 1877 Type StatsType `json:"type"` 1878 1879 // ID is a unique id that is associated with the component inspected to produce 1880 // this Stats object. Two Stats objects will have the same ID if they were produced 1881 // by inspecting the same underlying object. 1882 ID string `json:"id"` 1883 1884 // PacketsSent represents the total number of packets sent over this transport. 1885 PacketsSent uint32 `json:"packetsSent"` 1886 1887 // PacketsReceived represents the total number of packets received on this transport. 1888 PacketsReceived uint32 `json:"packetsReceived"` 1889 1890 // BytesSent represents the total number of payload bytes sent on this PeerConnection 1891 // not including headers or padding. 1892 BytesSent uint64 `json:"bytesSent"` 1893 1894 // BytesReceived represents the total number of bytes received on this PeerConnection 1895 // not including headers or padding. 1896 BytesReceived uint64 `json:"bytesReceived"` 1897 1898 // RTCPTransportStatsID is the ID of the transport that gives stats for the RTCP 1899 // component If RTP and RTCP are not multiplexed and this record has only 1900 // the RTP component stats. 1901 RTCPTransportStatsID string `json:"rtcpTransportStatsId"` 1902 1903 // ICERole is set to the current value of the "role" attribute of the underlying 1904 // DTLSTransport's "iceTransport". 1905 ICERole ICERole `json:"iceRole"` 1906 1907 // DTLSState is set to the current value of the "state" attribute of the underlying DTLSTransport. 1908 DTLSState DTLSTransportState `json:"dtlsState"` 1909 1910 // ICEState is set to the current value of the "state" attribute of the underlying 1911 // RTCIceTransport's "state". 1912 ICEState ICETransportState `json:"iceState"` 1913 1914 // SelectedCandidatePairID is a unique identifier that is associated to the object 1915 // that was inspected to produce the ICECandidatePairStats associated with this transport. 1916 SelectedCandidatePairID string `json:"selectedCandidatePairId"` 1917 1918 // LocalCertificateID is the ID of the CertificateStats for the local certificate. 1919 // Present only if DTLS is negotiated. 1920 LocalCertificateID string `json:"localCertificateId"` 1921 1922 // LocalCertificateID is the ID of the CertificateStats for the remote certificate. 1923 // Present only if DTLS is negotiated. 1924 RemoteCertificateID string `json:"remoteCertificateId"` 1925 1926 // DTLSCipher is the descriptive name of the cipher suite used for the DTLS transport, 1927 // as defined in the "Description" column of the IANA cipher suite registry. 1928 DTLSCipher string `json:"dtlsCipher"` 1929 1930 // SRTPCipher is the descriptive name of the protection profile used for the SRTP 1931 // transport, as defined in the "Profile" column of the IANA DTLS-SRTP protection 1932 // profile registry. 1933 SRTPCipher string `json:"srtpCipher"` 1934 } 1935 1936 func (s TransportStats) statsMarker() {} 1937 1938 func unmarshalTransportStats(b []byte) (TransportStats, error) { 1939 var transportStats TransportStats 1940 err := json.Unmarshal(b, &transportStats) 1941 if err != nil { 1942 return TransportStats{}, fmt.Errorf("unmarshal transport stats: %w", err) 1943 } 1944 return transportStats, nil 1945 } 1946 1947 // StatsICECandidatePairState is the state of an ICE candidate pair used in the 1948 // ICECandidatePairStats object. 1949 type StatsICECandidatePairState string 1950 1951 func toStatsICECandidatePairState(state ice.CandidatePairState) (StatsICECandidatePairState, error) { 1952 switch state { 1953 case ice.CandidatePairStateWaiting: 1954 return StatsICECandidatePairStateWaiting, nil 1955 case ice.CandidatePairStateInProgress: 1956 return StatsICECandidatePairStateInProgress, nil 1957 case ice.CandidatePairStateFailed: 1958 return StatsICECandidatePairStateFailed, nil 1959 case ice.CandidatePairStateSucceeded: 1960 return StatsICECandidatePairStateSucceeded, nil 1961 default: 1962 // NOTE: this should never happen[tm] 1963 err := fmt.Errorf("%w: %s", errStatsICECandidateStateInvalid, state.String()) 1964 return StatsICECandidatePairState("Unknown"), err 1965 } 1966 } 1967 1968 func toICECandidatePairStats(candidatePairStats ice.CandidatePairStats) (ICECandidatePairStats, error) { 1969 state, err := toStatsICECandidatePairState(candidatePairStats.State) 1970 if err != nil { 1971 return ICECandidatePairStats{}, err 1972 } 1973 1974 return ICECandidatePairStats{ 1975 Timestamp: statsTimestampFrom(candidatePairStats.Timestamp), 1976 Type: StatsTypeCandidatePair, 1977 ID: newICECandidatePairStatsID(candidatePairStats.LocalCandidateID, candidatePairStats.RemoteCandidateID), 1978 // TransportID: 1979 LocalCandidateID: candidatePairStats.LocalCandidateID, 1980 RemoteCandidateID: candidatePairStats.RemoteCandidateID, 1981 State: state, 1982 Nominated: candidatePairStats.Nominated, 1983 PacketsSent: candidatePairStats.PacketsSent, 1984 PacketsReceived: candidatePairStats.PacketsReceived, 1985 BytesSent: candidatePairStats.BytesSent, 1986 BytesReceived: candidatePairStats.BytesReceived, 1987 LastPacketSentTimestamp: statsTimestampFrom(candidatePairStats.LastPacketSentTimestamp), 1988 LastPacketReceivedTimestamp: statsTimestampFrom(candidatePairStats.LastPacketReceivedTimestamp), 1989 FirstRequestTimestamp: statsTimestampFrom(candidatePairStats.FirstRequestTimestamp), 1990 LastRequestTimestamp: statsTimestampFrom(candidatePairStats.LastRequestTimestamp), 1991 LastResponseTimestamp: statsTimestampFrom(candidatePairStats.LastResponseTimestamp), 1992 TotalRoundTripTime: candidatePairStats.TotalRoundTripTime, 1993 CurrentRoundTripTime: candidatePairStats.CurrentRoundTripTime, 1994 AvailableOutgoingBitrate: candidatePairStats.AvailableOutgoingBitrate, 1995 AvailableIncomingBitrate: candidatePairStats.AvailableIncomingBitrate, 1996 CircuitBreakerTriggerCount: candidatePairStats.CircuitBreakerTriggerCount, 1997 RequestsReceived: candidatePairStats.RequestsReceived, 1998 RequestsSent: candidatePairStats.RequestsSent, 1999 ResponsesReceived: candidatePairStats.ResponsesReceived, 2000 ResponsesSent: candidatePairStats.ResponsesSent, 2001 RetransmissionsReceived: candidatePairStats.RetransmissionsReceived, 2002 RetransmissionsSent: candidatePairStats.RetransmissionsSent, 2003 ConsentRequestsSent: candidatePairStats.ConsentRequestsSent, 2004 ConsentExpiredTimestamp: statsTimestampFrom(candidatePairStats.ConsentExpiredTimestamp), 2005 }, nil 2006 } 2007 2008 const ( 2009 // StatsICECandidatePairStateFrozen means a check for this pair hasn't been 2010 // performed, and it can't yet be performed until some other check succeeds, 2011 // allowing this pair to unfreeze and move into the Waiting state. 2012 StatsICECandidatePairStateFrozen StatsICECandidatePairState = "frozen" 2013 2014 // StatsICECandidatePairStateWaiting means a check has not been performed for 2015 // this pair, and can be performed as soon as it is the highest-priority Waiting 2016 // pair on the check list. 2017 StatsICECandidatePairStateWaiting StatsICECandidatePairState = "waiting" 2018 2019 // StatsICECandidatePairStateInProgress means a check has been sent for this pair, 2020 // but the transaction is in progress. 2021 StatsICECandidatePairStateInProgress StatsICECandidatePairState = "in-progress" 2022 2023 // StatsICECandidatePairStateFailed means a check for this pair was already done 2024 // and failed, either never producing any response or producing an unrecoverable 2025 // failure response. 2026 StatsICECandidatePairStateFailed StatsICECandidatePairState = "failed" 2027 2028 // StatsICECandidatePairStateSucceeded means a check for this pair was already 2029 // done and produced a successful result. 2030 StatsICECandidatePairStateSucceeded StatsICECandidatePairState = "succeeded" 2031 ) 2032 2033 // ICECandidatePairStats contains ICE candidate pair statistics related 2034 // to the ICETransport objects. 2035 type ICECandidatePairStats struct { 2036 // Timestamp is the timestamp associated with this object. 2037 Timestamp StatsTimestamp `json:"timestamp"` 2038 2039 // Type is the object's StatsType 2040 Type StatsType `json:"type"` 2041 2042 // ID is a unique id that is associated with the component inspected to produce 2043 // this Stats object. Two Stats objects will have the same ID if they were produced 2044 // by inspecting the same underlying object. 2045 ID string `json:"id"` 2046 2047 // TransportID is a unique identifier that is associated to the object that 2048 // was inspected to produce the TransportStats associated with this candidate pair. 2049 TransportID string `json:"transportId"` 2050 2051 // LocalCandidateID is a unique identifier that is associated to the object 2052 // that was inspected to produce the ICECandidateStats for the local candidate 2053 // associated with this candidate pair. 2054 LocalCandidateID string `json:"localCandidateId"` 2055 2056 // RemoteCandidateID is a unique identifier that is associated to the object 2057 // that was inspected to produce the ICECandidateStats for the remote candidate 2058 // associated with this candidate pair. 2059 RemoteCandidateID string `json:"remoteCandidateId"` 2060 2061 // State represents the state of the checklist for the local and remote 2062 // candidates in a pair. 2063 State StatsICECandidatePairState `json:"state"` 2064 2065 // Nominated is true when this valid pair that should be used for media 2066 // if it is the highest-priority one amongst those whose nominated flag is set 2067 Nominated bool `json:"nominated"` 2068 2069 // PacketsSent represents the total number of packets sent on this candidate pair. 2070 PacketsSent uint32 `json:"packetsSent"` 2071 2072 // PacketsReceived represents the total number of packets received on this candidate pair. 2073 PacketsReceived uint32 `json:"packetsReceived"` 2074 2075 // BytesSent represents the total number of payload bytes sent on this candidate pair 2076 // not including headers or padding. 2077 BytesSent uint64 `json:"bytesSent"` 2078 2079 // BytesReceived represents the total number of payload bytes received on this candidate pair 2080 // not including headers or padding. 2081 BytesReceived uint64 `json:"bytesReceived"` 2082 2083 // LastPacketSentTimestamp represents the timestamp at which the last packet was 2084 // sent on this particular candidate pair, excluding STUN packets. 2085 LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"` 2086 2087 // LastPacketReceivedTimestamp represents the timestamp at which the last packet 2088 // was received on this particular candidate pair, excluding STUN packets. 2089 LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"` 2090 2091 // FirstRequestTimestamp represents the timestamp at which the first STUN request 2092 // was sent on this particular candidate pair. 2093 FirstRequestTimestamp StatsTimestamp `json:"firstRequestTimestamp"` 2094 2095 // LastRequestTimestamp represents the timestamp at which the last STUN request 2096 // was sent on this particular candidate pair. The average interval between two 2097 // consecutive connectivity checks sent can be calculated with 2098 // (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent. 2099 LastRequestTimestamp StatsTimestamp `json:"lastRequestTimestamp"` 2100 2101 // LastResponseTimestamp represents the timestamp at which the last STUN response 2102 // was received on this particular candidate pair. 2103 LastResponseTimestamp StatsTimestamp `json:"lastResponseTimestamp"` 2104 2105 // TotalRoundTripTime represents the sum of all round trip time measurements 2106 // in seconds since the beginning of the session, based on STUN connectivity 2107 // check responses (ResponsesReceived), including those that reply to requests 2108 // that are sent in order to verify consent. The average round trip time can 2109 // be computed from TotalRoundTripTime by dividing it by ResponsesReceived. 2110 TotalRoundTripTime float64 `json:"totalRoundTripTime"` 2111 2112 // CurrentRoundTripTime represents the latest round trip time measured in seconds, 2113 // computed from both STUN connectivity checks, including those that are sent 2114 // for consent verification. 2115 CurrentRoundTripTime float64 `json:"currentRoundTripTime"` 2116 2117 // AvailableOutgoingBitrate is calculated by the underlying congestion control 2118 // by combining the available bitrate for all the outgoing RTP streams using 2119 // this candidate pair. The bitrate measurement does not count the size of the 2120 // IP or other transport layers like TCP or UDP. It is similar to the TIAS defined 2121 // in RFC 3890, i.e., it is measured in bits per second and the bitrate is calculated 2122 // over a 1 second window. 2123 AvailableOutgoingBitrate float64 `json:"availableOutgoingBitrate"` 2124 2125 // AvailableIncomingBitrate is calculated by the underlying congestion control 2126 // by combining the available bitrate for all the incoming RTP streams using 2127 // this candidate pair. The bitrate measurement does not count the size of the 2128 // IP or other transport layers like TCP or UDP. It is similar to the TIAS defined 2129 // in RFC 3890, i.e., it is measured in bits per second and the bitrate is 2130 // calculated over a 1 second window. 2131 AvailableIncomingBitrate float64 `json:"availableIncomingBitrate"` 2132 2133 // CircuitBreakerTriggerCount represents the number of times the circuit breaker 2134 // is triggered for this particular 5-tuple, ceasing transmission. 2135 CircuitBreakerTriggerCount uint32 `json:"circuitBreakerTriggerCount"` 2136 2137 // RequestsReceived represents the total number of connectivity check requests 2138 // received (including retransmissions). It is impossible for the receiver to 2139 // tell whether the request was sent in order to check connectivity or check 2140 // consent, so all connectivity checks requests are counted here. 2141 RequestsReceived uint64 `json:"requestsReceived"` 2142 2143 // RequestsSent represents the total number of connectivity check requests 2144 // sent (not including retransmissions). 2145 RequestsSent uint64 `json:"requestsSent"` 2146 2147 // ResponsesReceived represents the total number of connectivity check responses received. 2148 ResponsesReceived uint64 `json:"responsesReceived"` 2149 2150 // ResponsesSent represents the total number of connectivity check responses sent. 2151 // Since we cannot distinguish connectivity check requests and consent requests, 2152 // all responses are counted. 2153 ResponsesSent uint64 `json:"responsesSent"` 2154 2155 // RetransmissionsReceived represents the total number of connectivity check 2156 // request retransmissions received. 2157 RetransmissionsReceived uint64 `json:"retransmissionsReceived"` 2158 2159 // RetransmissionsSent represents the total number of connectivity check 2160 // request retransmissions sent. 2161 RetransmissionsSent uint64 `json:"retransmissionsSent"` 2162 2163 // ConsentRequestsSent represents the total number of consent requests sent. 2164 ConsentRequestsSent uint64 `json:"consentRequestsSent"` 2165 2166 // ConsentExpiredTimestamp represents the timestamp at which the latest valid 2167 // STUN binding response expired. 2168 ConsentExpiredTimestamp StatsTimestamp `json:"consentExpiredTimestamp"` 2169 2170 // PacketsDiscardedOnSend retpresents the total number of packets for this candidate pair 2171 // that have been discarded due to socket errors, i.e. a socket error occurred 2172 // when handing the packets to the socket. This might happen due to various reasons, 2173 // including full buffer or no available memory. 2174 PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` 2175 2176 // BytesDiscardedOnSend represents the total number of bytes for this candidate pair 2177 // that have been discarded due to socket errors, i.e. a socket error occurred 2178 // when handing the packets containing the bytes to the socket. This might happen due 2179 // to various reasons, including full buffer or no available memory. 2180 // Calculated as defined in [RFC3550] section 6.4.1. 2181 BytesDiscardedOnSend uint32 `json:"bytesDiscardedOnSend"` 2182 } 2183 2184 func (s ICECandidatePairStats) statsMarker() {} 2185 2186 func unmarshalICECandidatePairStats(b []byte) (ICECandidatePairStats, error) { 2187 var iceCandidatePairStats ICECandidatePairStats 2188 err := json.Unmarshal(b, &iceCandidatePairStats) 2189 if err != nil { 2190 return ICECandidatePairStats{}, fmt.Errorf("unmarshal ice candidate pair stats: %w", err) 2191 } 2192 return iceCandidatePairStats, nil 2193 } 2194 2195 // ICECandidateStats contains ICE candidate statistics related to the ICETransport objects. 2196 type ICECandidateStats struct { 2197 // Timestamp is the timestamp associated with this object. 2198 Timestamp StatsTimestamp `json:"timestamp"` 2199 2200 // Type is the object's StatsType 2201 Type StatsType `json:"type"` 2202 2203 // ID is a unique id that is associated with the component inspected to produce 2204 // this Stats object. Two Stats objects will have the same ID if they were produced 2205 // by inspecting the same underlying object. 2206 ID string `json:"id"` 2207 2208 // TransportID is a unique identifier that is associated to the object that 2209 // was inspected to produce the TransportStats associated with this candidate. 2210 TransportID string `json:"transportId"` 2211 2212 // NetworkType represents the type of network interface used by the base of a 2213 // local candidate (the address the ICE agent sends from). Only present for 2214 // local candidates; it's not possible to know what type of network interface 2215 // a remote candidate is using. 2216 // 2217 // Note: 2218 // This stat only tells you about the network interface used by the first "hop"; 2219 // it's possible that a connection will be bottlenecked by another type of network. 2220 // For example, when using Wi-Fi tethering, the networkType of the relevant candidate 2221 // would be "wifi", even when the next hop is over a cellular connection. 2222 // 2223 // DEPRECATED. Although it may still work in some browsers, the networkType property was deprecated for 2224 // preserving privacy. 2225 NetworkType string `json:"networkType,omitempty"` 2226 2227 // IP is the IP address of the candidate, allowing for IPv4 addresses and 2228 // IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed. 2229 IP string `json:"ip"` 2230 2231 // Port is the port number of the candidate. 2232 Port int32 `json:"port"` 2233 2234 // Protocol is one of udp and tcp. 2235 Protocol string `json:"protocol"` 2236 2237 // CandidateType is the "Type" field of the ICECandidate. 2238 CandidateType ICECandidateType `json:"candidateType"` 2239 2240 // Priority is the "Priority" field of the ICECandidate. 2241 Priority int32 `json:"priority"` 2242 2243 // URL is the URL of the TURN or STUN server indicated in the that translated 2244 // this IP address. It is the URL address surfaced in an PeerConnectionICEEvent. 2245 URL string `json:"url"` 2246 2247 // RelayProtocol is the protocol used by the endpoint to communicate with the 2248 // TURN server. This is only present for local candidates. Valid values for 2249 // the TURN URL protocol is one of udp, tcp, or tls. 2250 RelayProtocol string `json:"relayProtocol"` 2251 2252 // Deleted is true if the candidate has been deleted/freed. For host candidates, 2253 // this means that any network resources (typically a socket) associated with the 2254 // candidate have been released. For TURN candidates, this means the TURN allocation 2255 // is no longer active. 2256 // 2257 // Only defined for local candidates. For remote candidates, this property is not applicable. 2258 Deleted bool `json:"deleted"` 2259 } 2260 2261 func (s ICECandidateStats) statsMarker() {} 2262 2263 func unmarshalICECandidateStats(b []byte) (ICECandidateStats, error) { 2264 var iceCandidateStats ICECandidateStats 2265 err := json.Unmarshal(b, &iceCandidateStats) 2266 if err != nil { 2267 return ICECandidateStats{}, fmt.Errorf("unmarshal ice candidate stats: %w", err) 2268 } 2269 return iceCandidateStats, nil 2270 } 2271 2272 // CertificateStats contains information about a certificate used by an ICETransport. 2273 type CertificateStats struct { 2274 // Timestamp is the timestamp associated with this object. 2275 Timestamp StatsTimestamp `json:"timestamp"` 2276 2277 // Type is the object's StatsType 2278 Type StatsType `json:"type"` 2279 2280 // ID is a unique id that is associated with the component inspected to produce 2281 // this Stats object. Two Stats objects will have the same ID if they were produced 2282 // by inspecting the same underlying object. 2283 ID string `json:"id"` 2284 2285 // Fingerprint is the fingerprint of the certificate. 2286 Fingerprint string `json:"fingerprint"` 2287 2288 // FingerprintAlgorithm is the hash function used to compute the certificate fingerprint. For instance, "sha-256". 2289 FingerprintAlgorithm string `json:"fingerprintAlgorithm"` 2290 2291 // Base64Certificate is the DER-encoded base-64 representation of the certificate. 2292 Base64Certificate string `json:"base64Certificate"` 2293 2294 // IssuerCertificateID refers to the stats object that contains the next certificate 2295 // in the certificate chain. If the current certificate is at the end of the chain 2296 // (i.e. a self-signed certificate), this will not be set. 2297 IssuerCertificateID string `json:"issuerCertificateId"` 2298 } 2299 2300 func (s CertificateStats) statsMarker() {} 2301 2302 func unmarshalCertificateStats(b []byte) (CertificateStats, error) { 2303 var certificateStats CertificateStats 2304 err := json.Unmarshal(b, &certificateStats) 2305 if err != nil { 2306 return CertificateStats{}, fmt.Errorf("unmarshal certificate stats: %w", err) 2307 } 2308 return certificateStats, nil 2309 } 2310 2311 // SCTPTransportStats contains information about a certificate used by an SCTPTransport. 2312 type SCTPTransportStats struct { 2313 // Timestamp is the timestamp associated with this object. 2314 Timestamp StatsTimestamp `json:"timestamp"` 2315 2316 // Type is the object's StatsType 2317 Type StatsType `json:"type"` 2318 2319 // ID is a unique id that is associated with the component inspected to produce 2320 // this Stats object. Two Stats objects will have the same ID if they were produced 2321 // by inspecting the same underlying object. 2322 ID string `json:"id"` 2323 2324 // TransportID is the identifier of the object that was inspected to produce the 2325 // RTCTransportStats for the DTLSTransport and ICETransport supporting the SCTP transport. 2326 TransportID string `json:"transportId"` 2327 2328 // SmoothedRoundTripTime is the latest smoothed round-trip time value, corresponding to spinfo_srtt defined in [RFC6458] 2329 // but converted to seconds. If there has been no round-trip time measurements yet, this value is undefined. 2330 SmoothedRoundTripTime float64 `json:"smoothedRoundTripTime"` 2331 2332 // CongestionWindow is the latest congestion window, corresponding to spinfo_cwnd defined in [RFC6458]. 2333 CongestionWindow uint32 `json:"congestionWindow"` 2334 2335 // ReceiverWindow is the latest receiver window, corresponding to sstat_rwnd defined in [RFC6458]. 2336 ReceiverWindow uint32 `json:"receiverWindow"` 2337 2338 // MTU is the latest maximum transmission unit, corresponding to spinfo_mtu defined in [RFC6458]. 2339 MTU uint32 `json:"mtu"` 2340 2341 // UNACKData is the number of unacknowledged DATA chunks, corresponding to sstat_unackdata defined in [RFC6458]. 2342 UNACKData uint32 `json:"unackData"` 2343 2344 // BytesSent represents the total number of bytes sent on this SCTPTransport 2345 BytesSent uint64 `json:"bytesSent"` 2346 2347 // BytesReceived represents the total number of bytes received on this SCTPTransport 2348 BytesReceived uint64 `json:"bytesReceived"` 2349 } 2350 2351 func (s SCTPTransportStats) statsMarker() {} 2352 2353 func unmarshalSCTPTransportStats(b []byte) (SCTPTransportStats, error) { 2354 var sctpTransportStats SCTPTransportStats 2355 if err := json.Unmarshal(b, &sctpTransportStats); err != nil { 2356 return SCTPTransportStats{}, fmt.Errorf("unmarshal sctp transport stats: %w", err) 2357 } 2358 return sctpTransportStats, nil 2359 }