github.com/pion/webrtc/v3@v3.2.24/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/v2" 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 // Timestamp is the timestamp associated with this object. 279 Timestamp StatsTimestamp `json:"timestamp"` 280 281 // Type is the object's StatsType 282 Type StatsType `json:"type"` 283 284 // ID is a unique id that is associated with the component inspected to produce 285 // this Stats object. Two Stats objects will have the same ID if they were produced 286 // by inspecting the same underlying object. 287 ID string `json:"id"` 288 289 // SSRC is the 32-bit unsigned integer value used to identify the source of the 290 // stream of RTP packets that this stats object concerns. 291 SSRC SSRC `json:"ssrc"` 292 293 // Kind is either "audio" or "video" 294 Kind string `json:"kind"` 295 296 // It is a unique identifier that is associated to the object that was inspected 297 // to produce the TransportStats associated with this RTP stream. 298 TransportID string `json:"transportId"` 299 300 // CodecID is a unique identifier that is associated to the object that was inspected 301 // to produce the CodecStats associated with this RTP stream. 302 CodecID string `json:"codecId"` 303 304 // FIRCount counts the total number of Full Intra Request (FIR) packets received 305 // by the sender. This metric is only valid for video and is sent by receiver. 306 FIRCount uint32 `json:"firCount"` 307 308 // PLICount counts the total number of Picture Loss Indication (PLI) packets 309 // received by the sender. This metric is only valid for video and is sent by receiver. 310 PLICount uint32 `json:"pliCount"` 311 312 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 313 // received by the sender and is sent by receiver. 314 NACKCount uint32 `json:"nackCount"` 315 316 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 317 // by the sender. This metric is only valid for video and is sent by receiver. 318 SLICount uint32 `json:"sliCount"` 319 320 // QPSum is the sum of the QP values of frames passed. The count of frames is 321 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 322 QPSum uint64 `json:"qpSum"` 323 324 // PacketsReceived is the total number of RTP packets received for this SSRC. 325 PacketsReceived uint32 `json:"packetsReceived"` 326 327 // PacketsLost is the total number of RTP packets lost for this SSRC. Note that 328 // because of how this is estimated, it can be negative if more packets are received than sent. 329 PacketsLost int32 `json:"packetsLost"` 330 331 // Jitter is the packet jitter measured in seconds for this SSRC 332 Jitter float64 `json:"jitter"` 333 334 // PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter 335 // buffer due to late or early-arrival, i.e., these packets are not played out. 336 // RTP packets discarded due to packet duplication are not reported in this metric. 337 PacketsDiscarded uint32 `json:"packetsDiscarded"` 338 339 // PacketsRepaired is the cumulative number of lost RTP packets repaired after applying 340 // an error-resilience mechanism. It is measured for the primary source RTP packets 341 // and only counted for RTP packets that have no further chance of repair. 342 PacketsRepaired uint32 `json:"packetsRepaired"` 343 344 // BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts. 345 BurstPacketsLost uint32 `json:"burstPacketsLost"` 346 347 // BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts. 348 BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"` 349 350 // BurstLossCount is the cumulative number of bursts of lost RTP packets. 351 BurstLossCount uint32 `json:"burstLossCount"` 352 353 // BurstDiscardCount is the cumulative number of bursts of discarded RTP packets. 354 BurstDiscardCount uint32 `json:"burstDiscardCount"` 355 356 // BurstLossRate is the fraction of RTP packets lost during bursts to the 357 // total number of RTP packets expected in the bursts. 358 BurstLossRate float64 `json:"burstLossRate"` 359 360 // BurstDiscardRate is the fraction of RTP packets discarded during bursts to 361 // the total number of RTP packets expected in bursts. 362 BurstDiscardRate float64 `json:"burstDiscardRate"` 363 364 // GapLossRate is the fraction of RTP packets lost during the gap periods. 365 GapLossRate float64 `json:"gapLossRate"` 366 367 // GapDiscardRate is the fraction of RTP packets discarded during the gap periods. 368 GapDiscardRate float64 `json:"gapDiscardRate"` 369 370 // TrackID is the identifier of the stats object representing the receiving track, 371 // a ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats. 372 TrackID string `json:"trackId"` 373 374 // ReceiverID is the stats ID used to look up the AudioReceiverStats or VideoReceiverStats 375 // object receiving this stream. 376 ReceiverID string `json:"receiverId"` 377 378 // RemoteID is used for looking up the remote RemoteOutboundRTPStreamStats object 379 // for the same SSRC. 380 RemoteID string `json:"remoteId"` 381 382 // FramesDecoded represents the total number of frames correctly decoded for this SSRC, 383 // i.e., frames that would be displayed if no frames are dropped. Only valid for video. 384 FramesDecoded uint32 `json:"framesDecoded"` 385 386 // LastPacketReceivedTimestamp represents the timestamp at which the last packet was 387 // received for this SSRC. This differs from Timestamp, which represents the time 388 // at which the statistics were generated by the local endpoint. 389 LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"` 390 391 // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP packets. 392 // This is calculated by the sending endpoint when sending compound RTCP reports. 393 // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet 394 // with the CNAME item. 395 AverageRTCPInterval float64 `json:"averageRtcpInterval"` 396 397 // FECPacketsReceived is the total number of RTP FEC packets received for this SSRC. 398 // This counter can also be incremented when receiving FEC packets in-band with media packets (e.g., with Opus). 399 FECPacketsReceived uint32 `json:"fecPacketsReceived"` 400 401 // BytesReceived is the total number of bytes received for this SSRC. 402 BytesReceived uint64 `json:"bytesReceived"` 403 404 // PacketsFailedDecryption is the cumulative number of RTP packets that failed 405 // to be decrypted. These packets are not counted by PacketsDiscarded. 406 PacketsFailedDecryption uint32 `json:"packetsFailedDecryption"` 407 408 // PacketsDuplicated is the cumulative number of packets discarded because they 409 // are duplicated. Duplicate packets are not counted in PacketsDiscarded. 410 // 411 // Duplicated packets have the same RTP sequence number and content as a previously 412 // received packet. If multiple duplicates of a packet are received, all of them are counted. 413 // An improved estimate of lost packets can be calculated by adding PacketsDuplicated to PacketsLost. 414 PacketsDuplicated uint32 `json:"packetsDuplicated"` 415 416 // PerDSCPPacketsReceived is the total number of packets received for this SSRC, 417 // per Differentiated Services code point (DSCP) [RFC2474]. DSCPs are identified 418 // as decimal integers in string form. Note that due to network remapping and bleaching, 419 // these numbers are not expected to match the numbers seen on sending. Not all 420 // OSes make this information available. 421 PerDSCPPacketsReceived map[string]uint32 `json:"perDscpPacketsReceived"` 422 } 423 424 func (s InboundRTPStreamStats) statsMarker() {} 425 426 func unmarshalInboundRTPStreamStats(b []byte) (InboundRTPStreamStats, error) { 427 var inboundRTPStreamStats InboundRTPStreamStats 428 err := json.Unmarshal(b, &inboundRTPStreamStats) 429 if err != nil { 430 return InboundRTPStreamStats{}, fmt.Errorf("unmarshal inbound rtp stream stats: %w", err) 431 } 432 return inboundRTPStreamStats, nil 433 } 434 435 // QualityLimitationReason lists the reason for limiting the resolution and/or framerate. 436 // Only valid for video. 437 type QualityLimitationReason string 438 439 const ( 440 // QualityLimitationReasonNone means the resolution and/or framerate is not limited. 441 QualityLimitationReasonNone QualityLimitationReason = "none" 442 443 // QualityLimitationReasonCPU means the resolution and/or framerate is primarily limited due to CPU load. 444 QualityLimitationReasonCPU QualityLimitationReason = "cpu" 445 446 // 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. 447 QualityLimitationReasonBandwidth QualityLimitationReason = "bandwidth" 448 449 // QualityLimitationReasonOther means the resolution and/or framerate is primarily limited for a reason other than the above. 450 QualityLimitationReasonOther QualityLimitationReason = "other" 451 ) 452 453 // OutboundRTPStreamStats contains statistics for an outbound RTP stream that is 454 // currently sent with this PeerConnection object. 455 type OutboundRTPStreamStats struct { 456 // Timestamp is the timestamp associated with this object. 457 Timestamp StatsTimestamp `json:"timestamp"` 458 459 // Type is the object's StatsType 460 Type StatsType `json:"type"` 461 462 // ID is a unique id that is associated with the component inspected to produce 463 // this Stats object. Two Stats objects will have the same ID if they were produced 464 // by inspecting the same underlying object. 465 ID string `json:"id"` 466 467 // SSRC is the 32-bit unsigned integer value used to identify the source of the 468 // stream of RTP packets that this stats object concerns. 469 SSRC SSRC `json:"ssrc"` 470 471 // Kind is either "audio" or "video" 472 Kind string `json:"kind"` 473 474 // It is a unique identifier that is associated to the object that was inspected 475 // to produce the TransportStats associated with this RTP stream. 476 TransportID string `json:"transportId"` 477 478 // CodecID is a unique identifier that is associated to the object that was inspected 479 // to produce the CodecStats associated with this RTP stream. 480 CodecID string `json:"codecId"` 481 482 // FIRCount counts the total number of Full Intra Request (FIR) packets received 483 // by the sender. This metric is only valid for video and is sent by receiver. 484 FIRCount uint32 `json:"firCount"` 485 486 // PLICount counts the total number of Picture Loss Indication (PLI) packets 487 // received by the sender. This metric is only valid for video and is sent by receiver. 488 PLICount uint32 `json:"pliCount"` 489 490 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 491 // received by the sender and is sent by receiver. 492 NACKCount uint32 `json:"nackCount"` 493 494 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 495 // by the sender. This metric is only valid for video and is sent by receiver. 496 SLICount uint32 `json:"sliCount"` 497 498 // QPSum is the sum of the QP values of frames passed. The count of frames is 499 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 500 QPSum uint64 `json:"qpSum"` 501 502 // PacketsSent is the total number of RTP packets sent for this SSRC. 503 PacketsSent uint32 `json:"packetsSent"` 504 505 // PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that 506 // have been discarded due to socket errors, i.e. a socket error occurred when handing 507 // the packets to the socket. This might happen due to various reasons, including 508 // full buffer or no available memory. 509 PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` 510 511 // FECPacketsSent is the total number of RTP FEC packets sent for this SSRC. 512 // This counter can also be incremented when sending FEC packets in-band with 513 // media packets (e.g., with Opus). 514 FECPacketsSent uint32 `json:"fecPacketsSent"` 515 516 // BytesSent is the total number of bytes sent for this SSRC. 517 BytesSent uint64 `json:"bytesSent"` 518 519 // BytesDiscardedOnSend is the total number of bytes for this SSRC that have 520 // been discarded due to socket errors, i.e. a socket error occurred when handing 521 // the packets containing the bytes to the socket. This might happen due to various 522 // reasons, including full buffer or no available memory. 523 BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"` 524 525 // TrackID is the identifier of the stats object representing the current track 526 // attachment to the sender of this stream, a SenderAudioTrackAttachmentStats 527 // or SenderVideoTrackAttachmentStats. 528 TrackID string `json:"trackId"` 529 530 // SenderID is the stats ID used to look up the AudioSenderStats or VideoSenderStats 531 // object sending this stream. 532 SenderID string `json:"senderId"` 533 534 // RemoteID is used for looking up the remote RemoteInboundRTPStreamStats object 535 // for the same SSRC. 536 RemoteID string `json:"remoteId"` 537 538 // LastPacketSentTimestamp represents the timestamp at which the last packet was 539 // sent for this SSRC. This differs from timestamp, which represents the time at 540 // which the statistics were generated by the local endpoint. 541 LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"` 542 543 // TargetBitrate is the current target bitrate configured for this particular SSRC 544 // and is the Transport Independent Application Specific (TIAS) bitrate [RFC3890]. 545 // Typically, the target bitrate is a configuration parameter provided to the codec's 546 // encoder and does not count the size of the IP or other transport layers like TCP or UDP. 547 // It is measured in bits per second and the bitrate is calculated over a 1 second window. 548 TargetBitrate float64 `json:"targetBitrate"` 549 550 // FramesEncoded represents the total number of frames successfully encoded for this RTP media stream. 551 // Only valid for video. 552 FramesEncoded uint32 `json:"framesEncoded"` 553 554 // TotalEncodeTime is the total number of seconds that has been spent encoding the 555 // framesEncoded frames of this stream. The average encode time can be calculated by 556 // dividing this value with FramesEncoded. The time it takes to encode one frame is the 557 // time passed between feeding the encoder a frame and the encoder returning encoded data 558 // for that frame. This does not include any additional time it may take to packetize the resulting data. 559 TotalEncodeTime float64 `json:"totalEncodeTime"` 560 561 // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP 562 // packets. This is calculated by the sending endpoint when sending compound RTCP reports. 563 // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet with the CNAME item. 564 AverageRTCPInterval float64 `json:"averageRtcpInterval"` 565 566 // QualityLimitationReason is the current reason for limiting the resolution and/or framerate, 567 // or "none" if not limited. Only valid for video. 568 QualityLimitationReason QualityLimitationReason `json:"qualityLimitationReason"` 569 570 // QualityLimitationDurations is record of the total time, in seconds, that this 571 // stream has spent in each quality limitation state. The record includes a mapping 572 // for all QualityLimitationReason types, including "none". Only valid for video. 573 QualityLimitationDurations map[string]float64 `json:"qualityLimitationDurations"` 574 575 // PerDSCPPacketsSent is the total number of packets sent for this SSRC, per DSCP. 576 // DSCPs are identified as decimal integers in string form. 577 PerDSCPPacketsSent map[string]uint32 `json:"perDscpPacketsSent"` 578 } 579 580 func (s OutboundRTPStreamStats) statsMarker() {} 581 582 func unmarshalOutboundRTPStreamStats(b []byte) (OutboundRTPStreamStats, error) { 583 var outboundRTPStreamStats OutboundRTPStreamStats 584 err := json.Unmarshal(b, &outboundRTPStreamStats) 585 if err != nil { 586 return OutboundRTPStreamStats{}, fmt.Errorf("unmarshal outbound rtp stream stats: %w", err) 587 } 588 return outboundRTPStreamStats, nil 589 } 590 591 // RemoteInboundRTPStreamStats contains statistics for the remote endpoint's inbound 592 // RTP stream corresponding to an outbound stream that is currently sent with this 593 // PeerConnection object. It is measured at the remote endpoint and reported in an RTCP 594 // Receiver Report (RR) or RTCP Extended Report (XR). 595 type RemoteInboundRTPStreamStats struct { 596 // Timestamp is the timestamp associated with this object. 597 Timestamp StatsTimestamp `json:"timestamp"` 598 599 // Type is the object's StatsType 600 Type StatsType `json:"type"` 601 602 // ID is a unique id that is associated with the component inspected to produce 603 // this Stats object. Two Stats objects will have the same ID if they were produced 604 // by inspecting the same underlying object. 605 ID string `json:"id"` 606 607 // SSRC is the 32-bit unsigned integer value used to identify the source of the 608 // stream of RTP packets that this stats object concerns. 609 SSRC SSRC `json:"ssrc"` 610 611 // Kind is either "audio" or "video" 612 Kind string `json:"kind"` 613 614 // It is a unique identifier that is associated to the object that was inspected 615 // to produce the TransportStats associated with this RTP stream. 616 TransportID string `json:"transportId"` 617 618 // CodecID is a unique identifier that is associated to the object that was inspected 619 // to produce the CodecStats associated with this RTP stream. 620 CodecID string `json:"codecId"` 621 622 // FIRCount counts the total number of Full Intra Request (FIR) packets received 623 // by the sender. This metric is only valid for video and is sent by receiver. 624 FIRCount uint32 `json:"firCount"` 625 626 // PLICount counts the total number of Picture Loss Indication (PLI) packets 627 // received by the sender. This metric is only valid for video and is sent by receiver. 628 PLICount uint32 `json:"pliCount"` 629 630 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 631 // received by the sender and is sent by receiver. 632 NACKCount uint32 `json:"nackCount"` 633 634 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 635 // by the sender. This metric is only valid for video and is sent by receiver. 636 SLICount uint32 `json:"sliCount"` 637 638 // QPSum is the sum of the QP values of frames passed. The count of frames is 639 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 640 QPSum uint64 `json:"qpSum"` 641 642 // PacketsReceived is the total number of RTP packets received for this SSRC. 643 PacketsReceived uint32 `json:"packetsReceived"` 644 645 // PacketsLost is the total number of RTP packets lost for this SSRC. Note that 646 // because of how this is estimated, it can be negative if more packets are received than sent. 647 PacketsLost int32 `json:"packetsLost"` 648 649 // Jitter is the packet jitter measured in seconds for this SSRC 650 Jitter float64 `json:"jitter"` 651 652 // PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter 653 // buffer due to late or early-arrival, i.e., these packets are not played out. 654 // RTP packets discarded due to packet duplication are not reported in this metric. 655 PacketsDiscarded uint32 `json:"packetsDiscarded"` 656 657 // PacketsRepaired is the cumulative number of lost RTP packets repaired after applying 658 // an error-resilience mechanism. It is measured for the primary source RTP packets 659 // and only counted for RTP packets that have no further chance of repair. 660 PacketsRepaired uint32 `json:"packetsRepaired"` 661 662 // BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts. 663 BurstPacketsLost uint32 `json:"burstPacketsLost"` 664 665 // BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts. 666 BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"` 667 668 // BurstLossCount is the cumulative number of bursts of lost RTP packets. 669 BurstLossCount uint32 `json:"burstLossCount"` 670 671 // BurstDiscardCount is the cumulative number of bursts of discarded RTP packets. 672 BurstDiscardCount uint32 `json:"burstDiscardCount"` 673 674 // BurstLossRate is the fraction of RTP packets lost during bursts to the 675 // total number of RTP packets expected in the bursts. 676 BurstLossRate float64 `json:"burstLossRate"` 677 678 // BurstDiscardRate is the fraction of RTP packets discarded during bursts to 679 // the total number of RTP packets expected in bursts. 680 BurstDiscardRate float64 `json:"burstDiscardRate"` 681 682 // GapLossRate is the fraction of RTP packets lost during the gap periods. 683 GapLossRate float64 `json:"gapLossRate"` 684 685 // GapDiscardRate is the fraction of RTP packets discarded during the gap periods. 686 GapDiscardRate float64 `json:"gapDiscardRate"` 687 688 // LocalID is used for looking up the local OutboundRTPStreamStats object for the same SSRC. 689 LocalID string `json:"localId"` 690 691 // RoundTripTime is the estimated round trip time for this SSRC based on the 692 // RTCP timestamps in the RTCP Receiver Report (RR) and measured in seconds. 693 RoundTripTime float64 `json:"roundTripTime"` 694 695 // FractionLost is the fraction packet loss reported for this SSRC. 696 FractionLost float64 `json:"fractionLost"` 697 } 698 699 func (s RemoteInboundRTPStreamStats) statsMarker() {} 700 701 func unmarshalRemoteInboundRTPStreamStats(b []byte) (RemoteInboundRTPStreamStats, error) { 702 var remoteInboundRTPStreamStats RemoteInboundRTPStreamStats 703 err := json.Unmarshal(b, &remoteInboundRTPStreamStats) 704 if err != nil { 705 return RemoteInboundRTPStreamStats{}, fmt.Errorf("unmarshal remote inbound rtp stream stats: %w", err) 706 } 707 return remoteInboundRTPStreamStats, nil 708 } 709 710 // RemoteOutboundRTPStreamStats contains statistics for the remote endpoint's outbound 711 // RTP stream corresponding to an inbound stream that is currently received with this 712 // PeerConnection object. It is measured at the remote endpoint and reported in an 713 // RTCP Sender Report (SR). 714 type RemoteOutboundRTPStreamStats struct { 715 // Timestamp is the timestamp associated with this object. 716 Timestamp StatsTimestamp `json:"timestamp"` 717 718 // Type is the object's StatsType 719 Type StatsType `json:"type"` 720 721 // ID is a unique id that is associated with the component inspected to produce 722 // this Stats object. Two Stats objects will have the same ID if they were produced 723 // by inspecting the same underlying object. 724 ID string `json:"id"` 725 726 // SSRC is the 32-bit unsigned integer value used to identify the source of the 727 // stream of RTP packets that this stats object concerns. 728 SSRC SSRC `json:"ssrc"` 729 730 // Kind is either "audio" or "video" 731 Kind string `json:"kind"` 732 733 // It is a unique identifier that is associated to the object that was inspected 734 // to produce the TransportStats associated with this RTP stream. 735 TransportID string `json:"transportId"` 736 737 // CodecID is a unique identifier that is associated to the object that was inspected 738 // to produce the CodecStats associated with this RTP stream. 739 CodecID string `json:"codecId"` 740 741 // FIRCount counts the total number of Full Intra Request (FIR) packets received 742 // by the sender. This metric is only valid for video and is sent by receiver. 743 FIRCount uint32 `json:"firCount"` 744 745 // PLICount counts the total number of Picture Loss Indication (PLI) packets 746 // received by the sender. This metric is only valid for video and is sent by receiver. 747 PLICount uint32 `json:"pliCount"` 748 749 // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets 750 // received by the sender and is sent by receiver. 751 NACKCount uint32 `json:"nackCount"` 752 753 // SLICount counts the total number of Slice Loss Indication (SLI) packets received 754 // by the sender. This metric is only valid for video and is sent by receiver. 755 SLICount uint32 `json:"sliCount"` 756 757 // QPSum is the sum of the QP values of frames passed. The count of frames is 758 // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. 759 QPSum uint64 `json:"qpSum"` 760 761 // PacketsSent is the total number of RTP packets sent for this SSRC. 762 PacketsSent uint32 `json:"packetsSent"` 763 764 // PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that 765 // have been discarded due to socket errors, i.e. a socket error occurred when handing 766 // the packets to the socket. This might happen due to various reasons, including 767 // full buffer or no available memory. 768 PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` 769 770 // FECPacketsSent is the total number of RTP FEC packets sent for this SSRC. 771 // This counter can also be incremented when sending FEC packets in-band with 772 // media packets (e.g., with Opus). 773 FECPacketsSent uint32 `json:"fecPacketsSent"` 774 775 // BytesSent is the total number of bytes sent for this SSRC. 776 BytesSent uint64 `json:"bytesSent"` 777 778 // BytesDiscardedOnSend is the total number of bytes for this SSRC that have 779 // been discarded due to socket errors, i.e. a socket error occurred when handing 780 // the packets containing the bytes to the socket. This might happen due to various 781 // reasons, including full buffer or no available memory. 782 BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"` 783 784 // LocalID is used for looking up the local InboundRTPStreamStats object for the same SSRC. 785 LocalID string `json:"localId"` 786 787 // RemoteTimestamp represents the remote timestamp at which these statistics were 788 // sent by the remote endpoint. This differs from timestamp, which represents the 789 // time at which the statistics were generated or received by the local endpoint. 790 // The RemoteTimestamp, if present, is derived from the NTP timestamp in an RTCP 791 // Sender Report (SR) packet, which reflects the remote endpoint's clock. 792 // That clock may not be synchronized with the local clock. 793 RemoteTimestamp StatsTimestamp `json:"remoteTimestamp"` 794 } 795 796 func (s RemoteOutboundRTPStreamStats) statsMarker() {} 797 798 func unmarshalRemoteOutboundRTPStreamStats(b []byte) (RemoteOutboundRTPStreamStats, error) { 799 var remoteOutboundRTPStreamStats RemoteOutboundRTPStreamStats 800 err := json.Unmarshal(b, &remoteOutboundRTPStreamStats) 801 if err != nil { 802 return RemoteOutboundRTPStreamStats{}, fmt.Errorf("unmarshal remote outbound rtp stream stats: %w", err) 803 } 804 return remoteOutboundRTPStreamStats, nil 805 } 806 807 // RTPContributingSourceStats contains statistics for a contributing source (CSRC) that contributed 808 // to an inbound RTP stream. 809 type RTPContributingSourceStats struct { 810 // Timestamp is the timestamp associated with this object. 811 Timestamp StatsTimestamp `json:"timestamp"` 812 813 // Type is the object's StatsType 814 Type StatsType `json:"type"` 815 816 // ID is a unique id that is associated with the component inspected to produce 817 // this Stats object. Two Stats objects will have the same ID if they were produced 818 // by inspecting the same underlying object. 819 ID string `json:"id"` 820 821 // ContributorSSRC is the SSRC identifier of the contributing source represented 822 // by this stats object. It is a 32-bit unsigned integer that appears in the CSRC 823 // list of any packets the relevant source contributed to. 824 ContributorSSRC SSRC `json:"contributorSsrc"` 825 826 // InboundRTPStreamID is the ID of the InboundRTPStreamStats object representing 827 // the inbound RTP stream that this contributing source is contributing to. 828 InboundRTPStreamID string `json:"inboundRtpStreamId"` 829 830 // PacketsContributedTo is the total number of RTP packets that this contributing 831 // source contributed to. This value is incremented each time a packet is counted 832 // by InboundRTPStreamStats.packetsReceived, and the packet's CSRC list contains 833 // the SSRC identifier of this contributing source, ContributorSSRC. 834 PacketsContributedTo uint32 `json:"packetsContributedTo"` 835 836 // AudioLevel is present if the last received RTP packet that this source contributed 837 // to contained an [RFC6465] mixer-to-client audio level header extension. The value 838 // of audioLevel is between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents 839 // silence, and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov. 840 AudioLevel float64 `json:"audioLevel"` 841 } 842 843 func (s RTPContributingSourceStats) statsMarker() {} 844 845 func unmarshalCSRCStats(b []byte) (RTPContributingSourceStats, error) { 846 var csrcStats RTPContributingSourceStats 847 err := json.Unmarshal(b, &csrcStats) 848 if err != nil { 849 return RTPContributingSourceStats{}, fmt.Errorf("unmarshal csrc stats: %w", err) 850 } 851 return csrcStats, nil 852 } 853 854 // AudioSourceStats represents an audio track that is attached to one or more senders. 855 type AudioSourceStats struct { 856 // Timestamp is the timestamp associated with this object. 857 Timestamp StatsTimestamp `json:"timestamp"` 858 859 // Type is the object's StatsType 860 Type StatsType `json:"type"` 861 862 // ID is a unique id that is associated with the component inspected to produce 863 // this Stats object. Two Stats objects will have the same ID if they were produced 864 // by inspecting the same underlying object. 865 ID string `json:"id"` 866 867 // TrackIdentifier represents the id property of the track. 868 TrackIdentifier string `json:"trackIdentifier"` 869 870 // Kind is "audio" 871 Kind string `json:"kind"` 872 873 // AudioLevel represents the output audio level of the track. 874 // 875 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 876 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 877 // the sound pressure level from 0 dBov. 878 // 879 // If the track is sourced from an Receiver, does no audio processing, has a 880 // constant level, and has a volume setting of 1.0, the audio level is expected 881 // to be the same as the audio level of the source SSRC, while if the volume setting 882 // is 0.5, the AudioLevel is expected to be half that value. 883 AudioLevel float64 `json:"audioLevel"` 884 885 // TotalAudioEnergy is the total energy of all the audio samples sent/received 886 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 887 // each audio sample seen. 888 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 889 890 // TotalSamplesDuration represents the total duration in seconds of all samples 891 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 892 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 893 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 894 895 // EchoReturnLoss is only present while the sender is sending a track sourced from 896 // a microphone where echo cancellation is applied. Calculated in decibels. 897 EchoReturnLoss float64 `json:"echoReturnLoss"` 898 899 // EchoReturnLossEnhancement is only present while the sender is sending a track 900 // sourced from a microphone where echo cancellation is applied. Calculated in decibels. 901 EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"` 902 903 // DroppedSamplesDuration represents the total duration, in seconds, of samples produced by the device that got 904 // dropped before reaching the media source. Only applicable if this media source is backed by an audio capture device. 905 DroppedSamplesDuration float64 `json:"droppedSamplesDuration"` 906 907 // DroppedSamplesEvents is the number of dropped samples events. This counter increases every time a sample is 908 // dropped after a non-dropped sample. That is, multiple consecutive dropped samples will increase 909 // droppedSamplesDuration multiple times but is a single dropped samples event. 910 DroppedSamplesEvents uint64 `json:"droppedSamplesEvents"` 911 912 // TotalCaptureDelay is the total delay, in seconds, for each audio sample between the time the sample was emitted 913 // by the capture device and the sample reaching the source. This can be used together with totalSamplesCaptured to 914 // calculate the average capture delay per sample. Only applicable if the audio source represents an audio capture device. 915 TotalCaptureDelay float64 `json:"totalCaptureDelay"` 916 917 // TotalSamplesCaptured is the total number of captured samples reaching the audio source, i.e. that were not dropped 918 // by the capture pipeline. The frequency of the media source is not necessarily the same as the frequency of encoders 919 // later in the pipeline. Only applicable if the audio source represents an audio capture device. 920 TotalSamplesCaptured uint64 `json:"totalSamplesCaptured"` 921 } 922 923 func (s AudioSourceStats) statsMarker() {} 924 925 // VideoSourceStats represents a video track that is attached to one or more senders. 926 type VideoSourceStats struct { 927 // Timestamp is the timestamp associated with this object. 928 Timestamp StatsTimestamp `json:"timestamp"` 929 930 // Type is the object's StatsType 931 Type StatsType `json:"type"` 932 933 // ID is a unique id that is associated with the component inspected to produce 934 // this Stats object. Two Stats objects will have the same ID if they were produced 935 // by inspecting the same underlying object. 936 ID string `json:"id"` 937 938 // TrackIdentifier represents the id property of the track. 939 TrackIdentifier string `json:"trackIdentifier"` 940 941 // Kind is "video" 942 Kind string `json:"kind"` 943 944 // Width is width of the last frame originating from this source in pixels. 945 Width uint32 `json:"width"` 946 947 // Height is height of the last frame originating from this source in pixels. 948 Height uint32 `json:"height"` 949 950 // Frames is the total number of frames originating from this source. 951 Frames uint32 `json:"frames"` 952 953 // FramesPerSecond is the number of frames originating from this source, measured during the last second. 954 FramesPerSecond float64 `json:"framesPerSecond"` 955 } 956 957 func (s VideoSourceStats) statsMarker() {} 958 959 func unmarshalMediaSourceStats(b []byte) (Stats, error) { 960 type kindJSON struct { 961 Kind string `json:"kind"` 962 } 963 kindHolder := kindJSON{} 964 965 err := json.Unmarshal(b, &kindHolder) 966 if err != nil { 967 return nil, fmt.Errorf("unmarshal json kind: %w", err) 968 } 969 970 switch MediaKind(kindHolder.Kind) { 971 case MediaKindAudio: 972 var mediaSourceStats AudioSourceStats 973 err := json.Unmarshal(b, &mediaSourceStats) 974 if err != nil { 975 return nil, fmt.Errorf("unmarshal audio source stats: %w", err) 976 } 977 return mediaSourceStats, nil 978 case MediaKindVideo: 979 var mediaSourceStats VideoSourceStats 980 err := json.Unmarshal(b, &mediaSourceStats) 981 if err != nil { 982 return nil, fmt.Errorf("unmarshal video source stats: %w", err) 983 } 984 return mediaSourceStats, nil 985 default: 986 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 987 } 988 } 989 990 // AudioPlayoutStats represents one playout path - if the same playout stats object is referenced by multiple 991 // RTCInboundRtpStreamStats this is an indication that audio mixing is happening in which case sample counters in this 992 // stats object refer to the samples after mixing. Only applicable if the playout path represents an audio device. 993 type AudioPlayoutStats struct { 994 // Timestamp is the timestamp associated with this object. 995 Timestamp StatsTimestamp `json:"timestamp"` 996 997 // Type is the object's StatsType 998 Type StatsType `json:"type"` 999 1000 // ID is a unique id that is associated with the component inspected to produce 1001 // this Stats object. Two Stats objects will have the same ID if they were produced 1002 // by inspecting the same underlying object. 1003 ID string `json:"id"` 1004 1005 // Kind is "audio" 1006 Kind string `json:"kind"` 1007 1008 // SynthesizedSamplesDuration is measured in seconds and is incremented each time an audio sample is synthesized by 1009 // this playout path. This metric can be used together with totalSamplesDuration to calculate the percentage of played 1010 // out media being synthesized. If the playout path is unable to produce audio samples on time for device playout, 1011 // samples are synthesized to be playout out instead. Synthesization typically only happens if the pipeline is 1012 // underperforming. Samples synthesized by the RTCInboundRtpStreamStats are not counted for here, but in 1013 // InboundRtpStreamStats.concealedSamples. 1014 SynthesizedSamplesDuration float64 `json:"synthesizedSamplesDuration"` 1015 1016 // SynthesizedSamplesEvents is the number of synthesized samples events. This counter increases every time a sample 1017 // is synthesized after a non-synthesized sample. That is, multiple consecutive synthesized samples will increase 1018 // synthesizedSamplesDuration multiple times but is a single synthesization samples event. 1019 SynthesizedSamplesEvents uint64 `json:"synthesizedSamplesEvents"` 1020 1021 // TotalSamplesDuration represents the total duration in seconds of all samples 1022 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1023 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1024 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1025 1026 // When audio samples are pulled by the playout device, this counter is incremented with the estimated delay of the 1027 // playout path for that audio sample. The playout delay includes the delay from being emitted to the actual time of 1028 // playout on the device. This metric can be used together with totalSamplesCount to calculate the average 1029 // playout delay per sample. 1030 TotalPlayoutDelay float64 `json:"totalPlayoutDelay"` 1031 1032 // When audio samples are pulled by the playout device, this counter is incremented with the number of samples 1033 // emitted for playout. 1034 TotalSamplesCount uint64 `json:"totalSamplesCount"` 1035 } 1036 1037 func (s AudioPlayoutStats) statsMarker() {} 1038 1039 func unmarshalMediaPlayoutStats(b []byte) (Stats, error) { 1040 var audioPlayoutStats AudioPlayoutStats 1041 err := json.Unmarshal(b, &audioPlayoutStats) 1042 if err != nil { 1043 return nil, fmt.Errorf("unmarshal audio playout stats: %w", err) 1044 } 1045 return audioPlayoutStats, nil 1046 } 1047 1048 // PeerConnectionStats contains statistics related to the PeerConnection object. 1049 type PeerConnectionStats struct { 1050 // Timestamp is the timestamp associated with this object. 1051 Timestamp StatsTimestamp `json:"timestamp"` 1052 1053 // Type is the object's StatsType 1054 Type StatsType `json:"type"` 1055 1056 // ID is a unique id that is associated with the component inspected to produce 1057 // this Stats object. Two Stats objects will have the same ID if they were produced 1058 // by inspecting the same underlying object. 1059 ID string `json:"id"` 1060 1061 // DataChannelsOpened represents the number of unique DataChannels that have 1062 // entered the "open" state during their lifetime. 1063 DataChannelsOpened uint32 `json:"dataChannelsOpened"` 1064 1065 // DataChannelsClosed represents the number of unique DataChannels that have 1066 // left the "open" state during their lifetime (due to being closed by either 1067 // end or the underlying transport being closed). DataChannels that transition 1068 // from "connecting" to "closing" or "closed" without ever being "open" 1069 // are not counted in this number. 1070 DataChannelsClosed uint32 `json:"dataChannelsClosed"` 1071 1072 // DataChannelsRequested Represents the number of unique DataChannels returned 1073 // from a successful createDataChannel() call on the PeerConnection. If the 1074 // underlying data transport is not established, these may be in the "connecting" state. 1075 DataChannelsRequested uint32 `json:"dataChannelsRequested"` 1076 1077 // DataChannelsAccepted represents the number of unique DataChannels signaled 1078 // in a "datachannel" event on the PeerConnection. 1079 DataChannelsAccepted uint32 `json:"dataChannelsAccepted"` 1080 } 1081 1082 func (s PeerConnectionStats) statsMarker() {} 1083 1084 func unmarshalPeerConnectionStats(b []byte) (PeerConnectionStats, error) { 1085 var pcStats PeerConnectionStats 1086 err := json.Unmarshal(b, &pcStats) 1087 if err != nil { 1088 return PeerConnectionStats{}, fmt.Errorf("unmarshal pc stats: %w", err) 1089 } 1090 return pcStats, nil 1091 } 1092 1093 // DataChannelStats contains statistics related to each DataChannel ID. 1094 type DataChannelStats struct { 1095 // Timestamp is the timestamp associated with this object. 1096 Timestamp StatsTimestamp `json:"timestamp"` 1097 1098 // Type is the object's StatsType 1099 Type StatsType `json:"type"` 1100 1101 // ID is a unique id that is associated with the component inspected to produce 1102 // this Stats object. Two Stats objects will have the same ID if they were produced 1103 // by inspecting the same underlying object. 1104 ID string `json:"id"` 1105 1106 // Label is the "label" value of the DataChannel object. 1107 Label string `json:"label"` 1108 1109 // Protocol is the "protocol" value of the DataChannel object. 1110 Protocol string `json:"protocol"` 1111 1112 // DataChannelIdentifier is the "id" attribute of the DataChannel object. 1113 DataChannelIdentifier int32 `json:"dataChannelIdentifier"` 1114 1115 // TransportID the ID of the TransportStats object for transport used to carry this datachannel. 1116 TransportID string `json:"transportId"` 1117 1118 // State is the "readyState" value of the DataChannel object. 1119 State DataChannelState `json:"state"` 1120 1121 // MessagesSent represents the total number of API "message" events sent. 1122 MessagesSent uint32 `json:"messagesSent"` 1123 1124 // BytesSent represents the total number of payload bytes sent on this 1125 // datachannel not including headers or padding. 1126 BytesSent uint64 `json:"bytesSent"` 1127 1128 // MessagesReceived represents the total number of API "message" events received. 1129 MessagesReceived uint32 `json:"messagesReceived"` 1130 1131 // BytesReceived represents the total number of bytes received on this 1132 // datachannel not including headers or padding. 1133 BytesReceived uint64 `json:"bytesReceived"` 1134 } 1135 1136 func (s DataChannelStats) statsMarker() {} 1137 1138 func unmarshalDataChannelStats(b []byte) (DataChannelStats, error) { 1139 var dataChannelStats DataChannelStats 1140 err := json.Unmarshal(b, &dataChannelStats) 1141 if err != nil { 1142 return DataChannelStats{}, fmt.Errorf("unmarshal data channel stats: %w", err) 1143 } 1144 return dataChannelStats, nil 1145 } 1146 1147 // MediaStreamStats contains statistics related to a specific MediaStream. 1148 type MediaStreamStats struct { 1149 // Timestamp is the timestamp associated with this object. 1150 Timestamp StatsTimestamp `json:"timestamp"` 1151 1152 // Type is the object's StatsType 1153 Type StatsType `json:"type"` 1154 1155 // ID is a unique id that is associated with the component inspected to produce 1156 // this Stats object. Two Stats objects will have the same ID if they were produced 1157 // by inspecting the same underlying object. 1158 ID string `json:"id"` 1159 1160 // StreamIdentifier is the "id" property of the MediaStream 1161 StreamIdentifier string `json:"streamIdentifier"` 1162 1163 // TrackIDs is a list of the identifiers of the stats object representing the 1164 // stream's tracks, either ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats. 1165 TrackIDs []string `json:"trackIds"` 1166 } 1167 1168 func (s MediaStreamStats) statsMarker() {} 1169 1170 func unmarshalStreamStats(b []byte) (MediaStreamStats, error) { 1171 var streamStats MediaStreamStats 1172 err := json.Unmarshal(b, &streamStats) 1173 if err != nil { 1174 return MediaStreamStats{}, fmt.Errorf("unmarshal stream stats: %w", err) 1175 } 1176 return streamStats, nil 1177 } 1178 1179 // AudioSenderStats represents the stats about one audio sender of a PeerConnection 1180 // object for which one calls GetStats. 1181 // 1182 // It appears in the stats as soon as the RTPSender is added by either AddTrack 1183 // or AddTransceiver, or by media negotiation. 1184 type AudioSenderStats struct { 1185 // Timestamp is the timestamp associated with this object. 1186 Timestamp StatsTimestamp `json:"timestamp"` 1187 1188 // Type is the object's StatsType 1189 Type StatsType `json:"type"` 1190 1191 // ID is a unique id that is associated with the component inspected to produce 1192 // this Stats object. Two Stats objects will have the same ID if they were produced 1193 // by inspecting the same underlying object. 1194 ID string `json:"id"` 1195 1196 // TrackIdentifier represents the id property of the track. 1197 TrackIdentifier string `json:"trackIdentifier"` 1198 1199 // RemoteSource is true if the source is remote, for instance if it is sourced 1200 // from another host via a PeerConnection. False otherwise. Only applicable for 'track' stats. 1201 RemoteSource bool `json:"remoteSource"` 1202 1203 // Ended reflects the "ended" state of the track. 1204 Ended bool `json:"ended"` 1205 1206 // Kind is "audio" 1207 Kind string `json:"kind"` 1208 1209 // AudioLevel represents the output audio level of the track. 1210 // 1211 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 1212 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 1213 // the sound pressure level from 0 dBov. 1214 // 1215 // If the track is sourced from an Receiver, does no audio processing, has a 1216 // constant level, and has a volume setting of 1.0, the audio level is expected 1217 // to be the same as the audio level of the source SSRC, while if the volume setting 1218 // is 0.5, the AudioLevel is expected to be half that value. 1219 // 1220 // For outgoing audio tracks, the AudioLevel is the level of the audio being sent. 1221 AudioLevel float64 `json:"audioLevel"` 1222 1223 // TotalAudioEnergy is the total energy of all the audio samples sent/received 1224 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 1225 // each audio sample seen. 1226 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 1227 1228 // VoiceActivityFlag represents whether the last RTP packet sent or played out 1229 // by this track contained voice activity or not based on the presence of the 1230 // V bit in the extension header, as defined in [RFC6464]. 1231 // 1232 // This value indicates the voice activity in the latest RTP packet played out 1233 // from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag. 1234 VoiceActivityFlag bool `json:"voiceActivityFlag"` 1235 1236 // TotalSamplesDuration represents the total duration in seconds of all samples 1237 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1238 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1239 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1240 1241 // EchoReturnLoss is only present while the sender is sending a track sourced from 1242 // a microphone where echo cancellation is applied. Calculated in decibels. 1243 EchoReturnLoss float64 `json:"echoReturnLoss"` 1244 1245 // EchoReturnLossEnhancement is only present while the sender is sending a track 1246 // sourced from a microphone where echo cancellation is applied. Calculated in decibels. 1247 EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"` 1248 1249 // TotalSamplesSent is the total number of samples that have been sent by this sender. 1250 TotalSamplesSent uint64 `json:"totalSamplesSent"` 1251 } 1252 1253 func (s AudioSenderStats) statsMarker() {} 1254 1255 // SenderAudioTrackAttachmentStats object represents the stats about one attachment 1256 // of an audio MediaStreamTrack to the PeerConnection object for which one calls GetStats. 1257 // 1258 // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver, 1259 // via ReplaceTrack on an RTPSender object). 1260 // 1261 // If an audio track is attached twice (via AddTransceiver or ReplaceTrack), there 1262 // will be two SenderAudioTrackAttachmentStats objects, one for each attachment. 1263 // They will have the same "TrackIdentifier" attribute, but different "ID" attributes. 1264 // 1265 // If the track is detached from the PeerConnection (via removeTrack or via replaceTrack), 1266 // it continues to appear, but with the "ObjectDeleted" member set to true. 1267 type SenderAudioTrackAttachmentStats AudioSenderStats 1268 1269 func (s SenderAudioTrackAttachmentStats) statsMarker() {} 1270 1271 // VideoSenderStats represents the stats about one video sender of a PeerConnection 1272 // object for which one calls GetStats. 1273 // 1274 // It appears in the stats as soon as the sender is added by either AddTrack or 1275 // AddTransceiver, or by media negotiation. 1276 type VideoSenderStats struct { 1277 // Timestamp is the timestamp associated with this object. 1278 Timestamp StatsTimestamp `json:"timestamp"` 1279 1280 // Type is the object's StatsType 1281 Type StatsType `json:"type"` 1282 1283 // ID is a unique id that is associated with the component inspected to produce 1284 // this Stats object. Two Stats objects will have the same ID if they were produced 1285 // by inspecting the same underlying object. 1286 ID string `json:"id"` 1287 1288 // Kind is "video" 1289 Kind string `json:"kind"` 1290 1291 // FramesCaptured represents the total number of frames captured, before encoding, 1292 // for this RTPSender (or for this MediaStreamTrack, if type is "track"). For example, 1293 // if type is "sender" and this sender's track represents a camera, then this is the 1294 // number of frames produced by the camera for this track while being sent by this sender, 1295 // combined with the number of frames produced by all tracks previously attached to this 1296 // sender while being sent by this sender. Framerates can vary due to hardware limitations 1297 // or environmental factors such as lighting conditions. 1298 FramesCaptured uint32 `json:"framesCaptured"` 1299 1300 // FramesSent represents the total number of frames sent by this RTPSender 1301 // (or for this MediaStreamTrack, if type is "track"). 1302 FramesSent uint32 `json:"framesSent"` 1303 1304 // HugeFramesSent represents the total number of huge frames sent by this RTPSender 1305 // (or for this MediaStreamTrack, if type is "track"). Huge frames, by definition, 1306 // are frames that have an encoded size at least 2.5 times the average size of the frames. 1307 // The average size of the frames is defined as the target bitrate per second divided 1308 // by the target fps at the time the frame was encoded. These are usually complex 1309 // to encode frames with a lot of changes in the picture. This can be used to estimate, 1310 // e.g slide changes in the streamed presentation. If a huge frame is also a key frame, 1311 // then both counters HugeFramesSent and KeyFramesSent are incremented. 1312 HugeFramesSent uint32 `json:"hugeFramesSent"` 1313 1314 // KeyFramesSent represents the total number of key frames sent by this RTPSender 1315 // (or for this MediaStreamTrack, if type is "track"), such as Infra-frames in 1316 // VP8 [RFC6386] or I-frames in H.264 [RFC6184]. This is a subset of FramesSent. 1317 // FramesSent - KeyFramesSent gives you the number of delta frames sent. 1318 KeyFramesSent uint32 `json:"keyFramesSent"` 1319 } 1320 1321 func (s VideoSenderStats) statsMarker() {} 1322 1323 // SenderVideoTrackAttachmentStats represents the stats about one attachment of a 1324 // video MediaStreamTrack to the PeerConnection object for which one calls GetStats. 1325 // 1326 // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver, 1327 // via ReplaceTrack on an RTPSender object). 1328 // 1329 // If a video track is attached twice (via AddTransceiver or ReplaceTrack), there 1330 // will be two SenderVideoTrackAttachmentStats objects, one for each attachment. 1331 // They will have the same "TrackIdentifier" attribute, but different "ID" attributes. 1332 // 1333 // If the track is detached from the PeerConnection (via RemoveTrack or via ReplaceTrack), 1334 // it continues to appear, but with the "ObjectDeleted" member set to true. 1335 type SenderVideoTrackAttachmentStats VideoSenderStats 1336 1337 func (s SenderVideoTrackAttachmentStats) statsMarker() {} 1338 1339 func unmarshalSenderStats(b []byte) (Stats, error) { 1340 type kindJSON struct { 1341 Kind string `json:"kind"` 1342 } 1343 kindHolder := kindJSON{} 1344 1345 err := json.Unmarshal(b, &kindHolder) 1346 if err != nil { 1347 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1348 } 1349 1350 switch MediaKind(kindHolder.Kind) { 1351 case MediaKindAudio: 1352 var senderStats AudioSenderStats 1353 err := json.Unmarshal(b, &senderStats) 1354 if err != nil { 1355 return nil, fmt.Errorf("unmarshal audio sender stats: %w", err) 1356 } 1357 return senderStats, nil 1358 case MediaKindVideo: 1359 var senderStats VideoSenderStats 1360 err := json.Unmarshal(b, &senderStats) 1361 if err != nil { 1362 return nil, fmt.Errorf("unmarshal video sender stats: %w", err) 1363 } 1364 return senderStats, nil 1365 default: 1366 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1367 } 1368 } 1369 1370 func unmarshalTrackStats(b []byte) (Stats, error) { 1371 type kindJSON struct { 1372 Kind string `json:"kind"` 1373 } 1374 kindHolder := kindJSON{} 1375 1376 err := json.Unmarshal(b, &kindHolder) 1377 if err != nil { 1378 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1379 } 1380 1381 switch MediaKind(kindHolder.Kind) { 1382 case MediaKindAudio: 1383 var trackStats SenderAudioTrackAttachmentStats 1384 err := json.Unmarshal(b, &trackStats) 1385 if err != nil { 1386 return nil, fmt.Errorf("unmarshal audio track stats: %w", err) 1387 } 1388 return trackStats, nil 1389 case MediaKindVideo: 1390 var trackStats SenderVideoTrackAttachmentStats 1391 err := json.Unmarshal(b, &trackStats) 1392 if err != nil { 1393 return nil, fmt.Errorf("unmarshal video track stats: %w", err) 1394 } 1395 return trackStats, nil 1396 default: 1397 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1398 } 1399 } 1400 1401 // AudioReceiverStats contains audio metrics related to a specific receiver. 1402 type AudioReceiverStats struct { 1403 // Timestamp is the timestamp associated with this object. 1404 Timestamp StatsTimestamp `json:"timestamp"` 1405 1406 // Type is the object's StatsType 1407 Type StatsType `json:"type"` 1408 1409 // ID is a unique id that is associated with the component inspected to produce 1410 // this Stats object. Two Stats objects will have the same ID if they were produced 1411 // by inspecting the same underlying object. 1412 ID string `json:"id"` 1413 1414 // Kind is "audio" 1415 Kind string `json:"kind"` 1416 1417 // AudioLevel represents the output audio level of the track. 1418 // 1419 // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, 1420 // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in 1421 // the sound pressure level from 0 dBov. 1422 // 1423 // If the track is sourced from an Receiver, does no audio processing, has a 1424 // constant level, and has a volume setting of 1.0, the audio level is expected 1425 // to be the same as the audio level of the source SSRC, while if the volume setting 1426 // is 0.5, the AudioLevel is expected to be half that value. 1427 // 1428 // For outgoing audio tracks, the AudioLevel is the level of the audio being sent. 1429 AudioLevel float64 `json:"audioLevel"` 1430 1431 // TotalAudioEnergy is the total energy of all the audio samples sent/received 1432 // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for 1433 // each audio sample seen. 1434 TotalAudioEnergy float64 `json:"totalAudioEnergy"` 1435 1436 // VoiceActivityFlag represents whether the last RTP packet sent or played out 1437 // by this track contained voice activity or not based on the presence of the 1438 // V bit in the extension header, as defined in [RFC6464]. 1439 // 1440 // This value indicates the voice activity in the latest RTP packet played out 1441 // from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag. 1442 VoiceActivityFlag bool `json:"voiceActivityFlag"` 1443 1444 // TotalSamplesDuration represents the total duration in seconds of all samples 1445 // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). 1446 // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. 1447 TotalSamplesDuration float64 `json:"totalSamplesDuration"` 1448 1449 // EstimatedPlayoutTimestamp is the estimated playout time of this receiver's 1450 // track. The playout time is the NTP timestamp of the last playable sample that 1451 // has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP 1452 // timestamps), extrapolated with the time elapsed since it was ready to be played out. 1453 // This is the "current time" of the track in NTP clock time of the sender and 1454 // can be present even if there is no audio currently playing. 1455 // 1456 // This can be useful for estimating how much audio and video is out of 1457 // sync for two tracks from the same source: 1458 // AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp 1459 EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"` 1460 1461 // JitterBufferDelay is the sum of the time, in seconds, each sample takes from 1462 // the time it is received and to the time it exits the jitter buffer. 1463 // This increases upon samples exiting, having completed their time in the buffer 1464 // (incrementing JitterBufferEmittedCount). The average jitter buffer delay can 1465 // be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. 1466 JitterBufferDelay float64 `json:"jitterBufferDelay"` 1467 1468 // JitterBufferEmittedCount is the total number of samples that have come out 1469 // of the jitter buffer (increasing JitterBufferDelay). 1470 JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` 1471 1472 // TotalSamplesReceived is the total number of samples that have been received 1473 // by this receiver. This includes ConcealedSamples. 1474 TotalSamplesReceived uint64 `json:"totalSamplesReceived"` 1475 1476 // ConcealedSamples is the total number of samples that are concealed samples. 1477 // A concealed sample is a sample that is based on data that was synthesized 1478 // to conceal packet loss and does not represent incoming data. 1479 ConcealedSamples uint64 `json:"concealedSamples"` 1480 1481 // ConcealmentEvents is the number of concealment events. This counter increases 1482 // every time a concealed sample is synthesized after a non-concealed sample. 1483 // That is, multiple consecutive concealed samples will increase the concealedSamples 1484 // count multiple times but is a single concealment event. 1485 ConcealmentEvents uint64 `json:"concealmentEvents"` 1486 } 1487 1488 func (s AudioReceiverStats) statsMarker() {} 1489 1490 // VideoReceiverStats contains video metrics related to a specific receiver. 1491 type VideoReceiverStats struct { 1492 // Timestamp is the timestamp associated with this object. 1493 Timestamp StatsTimestamp `json:"timestamp"` 1494 1495 // Type is the object's StatsType 1496 Type StatsType `json:"type"` 1497 1498 // ID is a unique id that is associated with the component inspected to produce 1499 // this Stats object. Two Stats objects will have the same ID if they were produced 1500 // by inspecting the same underlying object. 1501 ID string `json:"id"` 1502 1503 // Kind is "video" 1504 Kind string `json:"kind"` 1505 1506 // FrameWidth represents the width of the last processed frame for this track. 1507 // Before the first frame is processed this attribute is missing. 1508 FrameWidth uint32 `json:"frameWidth"` 1509 1510 // FrameHeight represents the height of the last processed frame for this track. 1511 // Before the first frame is processed this attribute is missing. 1512 FrameHeight uint32 `json:"frameHeight"` 1513 1514 // FramesPerSecond represents the nominal FPS value before the degradation preference 1515 // is applied. It is the number of complete frames in the last second. For sending 1516 // tracks it is the current captured FPS and for the receiving tracks it is the 1517 // current decoding framerate. 1518 FramesPerSecond float64 `json:"framesPerSecond"` 1519 1520 // EstimatedPlayoutTimestamp is the estimated playout time of this receiver's 1521 // track. The playout time is the NTP timestamp of the last playable sample that 1522 // has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP 1523 // timestamps), extrapolated with the time elapsed since it was ready to be played out. 1524 // This is the "current time" of the track in NTP clock time of the sender and 1525 // can be present even if there is no audio currently playing. 1526 // 1527 // This can be useful for estimating how much audio and video is out of 1528 // sync for two tracks from the same source: 1529 // AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp 1530 EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"` 1531 1532 // JitterBufferDelay is the sum of the time, in seconds, each sample takes from 1533 // the time it is received and to the time it exits the jitter buffer. 1534 // This increases upon samples exiting, having completed their time in the buffer 1535 // (incrementing JitterBufferEmittedCount). The average jitter buffer delay can 1536 // be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. 1537 JitterBufferDelay float64 `json:"jitterBufferDelay"` 1538 1539 // JitterBufferEmittedCount is the total number of samples that have come out 1540 // of the jitter buffer (increasing JitterBufferDelay). 1541 JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` 1542 1543 // FramesReceived Represents the total number of complete frames received for 1544 // this receiver. This metric is incremented when the complete frame is received. 1545 FramesReceived uint32 `json:"framesReceived"` 1546 1547 // KeyFramesReceived represents the total number of complete key frames received 1548 // for this MediaStreamTrack, such as Infra-frames in VP8 [RFC6386] or I-frames 1549 // in H.264 [RFC6184]. This is a subset of framesReceived. `framesReceived - keyFramesReceived` 1550 // gives you the number of delta frames received. This metric is incremented when 1551 // the complete key frame is received. It is not incremented if a partial key 1552 // frames is received and sent for decoding, i.e., the frame could not be recovered 1553 // via retransmission or FEC. 1554 KeyFramesReceived uint32 `json:"keyFramesReceived"` 1555 1556 // FramesDecoded represents the total number of frames correctly decoded for this 1557 // SSRC, i.e., frames that would be displayed if no frames are dropped. 1558 FramesDecoded uint32 `json:"framesDecoded"` 1559 1560 // FramesDropped is the total number of frames dropped predecode or dropped 1561 // because the frame missed its display deadline for this receiver's track. 1562 FramesDropped uint32 `json:"framesDropped"` 1563 1564 // The cumulative number of partial frames lost. This metric is incremented when 1565 // the frame is sent to the decoder. If the partial frame is received and recovered 1566 // via retransmission or FEC before decoding, the FramesReceived counter is incremented. 1567 PartialFramesLost uint32 `json:"partialFramesLost"` 1568 1569 // FullFramesLost is the cumulative number of full frames lost. 1570 FullFramesLost uint32 `json:"fullFramesLost"` 1571 } 1572 1573 func (s VideoReceiverStats) statsMarker() {} 1574 1575 func unmarshalReceiverStats(b []byte) (Stats, error) { 1576 type kindJSON struct { 1577 Kind string `json:"kind"` 1578 } 1579 kindHolder := kindJSON{} 1580 1581 err := json.Unmarshal(b, &kindHolder) 1582 if err != nil { 1583 return nil, fmt.Errorf("unmarshal json kind: %w", err) 1584 } 1585 1586 switch MediaKind(kindHolder.Kind) { 1587 case MediaKindAudio: 1588 var receiverStats AudioReceiverStats 1589 err := json.Unmarshal(b, &receiverStats) 1590 if err != nil { 1591 return nil, fmt.Errorf("unmarshal audio receiver stats: %w", err) 1592 } 1593 return receiverStats, nil 1594 case MediaKindVideo: 1595 var receiverStats VideoReceiverStats 1596 err := json.Unmarshal(b, &receiverStats) 1597 if err != nil { 1598 return nil, fmt.Errorf("unmarshal video receiver stats: %w", err) 1599 } 1600 return receiverStats, nil 1601 default: 1602 return nil, fmt.Errorf("kind: %w", ErrUnknownType) 1603 } 1604 } 1605 1606 // TransportStats contains transport statistics related to the PeerConnection object. 1607 type TransportStats struct { 1608 // Timestamp is the timestamp associated with this object. 1609 Timestamp StatsTimestamp `json:"timestamp"` 1610 1611 // Type is the object's StatsType 1612 Type StatsType `json:"type"` 1613 1614 // ID is a unique id that is associated with the component inspected to produce 1615 // this Stats object. Two Stats objects will have the same ID if they were produced 1616 // by inspecting the same underlying object. 1617 ID string `json:"id"` 1618 1619 // PacketsSent represents the total number of packets sent over this transport. 1620 PacketsSent uint32 `json:"packetsSent"` 1621 1622 // PacketsReceived represents the total number of packets received on this transport. 1623 PacketsReceived uint32 `json:"packetsReceived"` 1624 1625 // BytesSent represents the total number of payload bytes sent on this PeerConnection 1626 // not including headers or padding. 1627 BytesSent uint64 `json:"bytesSent"` 1628 1629 // BytesReceived represents the total number of bytes received on this PeerConnection 1630 // not including headers or padding. 1631 BytesReceived uint64 `json:"bytesReceived"` 1632 1633 // RTCPTransportStatsID is the ID of the transport that gives stats for the RTCP 1634 // component If RTP and RTCP are not multiplexed and this record has only 1635 // the RTP component stats. 1636 RTCPTransportStatsID string `json:"rtcpTransportStatsId"` 1637 1638 // ICERole is set to the current value of the "role" attribute of the underlying 1639 // DTLSTransport's "transport". 1640 ICERole ICERole `json:"iceRole"` 1641 1642 // DTLSState is set to the current value of the "state" attribute of the underlying DTLSTransport. 1643 DTLSState DTLSTransportState `json:"dtlsState"` 1644 1645 // SelectedCandidatePairID is a unique identifier that is associated to the object 1646 // that was inspected to produce the ICECandidatePairStats associated with this transport. 1647 SelectedCandidatePairID string `json:"selectedCandidatePairId"` 1648 1649 // LocalCertificateID is the ID of the CertificateStats for the local certificate. 1650 // Present only if DTLS is negotiated. 1651 LocalCertificateID string `json:"localCertificateId"` 1652 1653 // LocalCertificateID is the ID of the CertificateStats for the remote certificate. 1654 // Present only if DTLS is negotiated. 1655 RemoteCertificateID string `json:"remoteCertificateId"` 1656 1657 // DTLSCipher is the descriptive name of the cipher suite used for the DTLS transport, 1658 // as defined in the "Description" column of the IANA cipher suite registry. 1659 DTLSCipher string `json:"dtlsCipher"` 1660 1661 // SRTPCipher is the descriptive name of the protection profile used for the SRTP 1662 // transport, as defined in the "Profile" column of the IANA DTLS-SRTP protection 1663 // profile registry. 1664 SRTPCipher string `json:"srtpCipher"` 1665 } 1666 1667 func (s TransportStats) statsMarker() {} 1668 1669 func unmarshalTransportStats(b []byte) (TransportStats, error) { 1670 var transportStats TransportStats 1671 err := json.Unmarshal(b, &transportStats) 1672 if err != nil { 1673 return TransportStats{}, fmt.Errorf("unmarshal transport stats: %w", err) 1674 } 1675 return transportStats, nil 1676 } 1677 1678 // StatsICECandidatePairState is the state of an ICE candidate pair used in the 1679 // ICECandidatePairStats object. 1680 type StatsICECandidatePairState string 1681 1682 func toStatsICECandidatePairState(state ice.CandidatePairState) (StatsICECandidatePairState, error) { 1683 switch state { 1684 case ice.CandidatePairStateWaiting: 1685 return StatsICECandidatePairStateWaiting, nil 1686 case ice.CandidatePairStateInProgress: 1687 return StatsICECandidatePairStateInProgress, nil 1688 case ice.CandidatePairStateFailed: 1689 return StatsICECandidatePairStateFailed, nil 1690 case ice.CandidatePairStateSucceeded: 1691 return StatsICECandidatePairStateSucceeded, nil 1692 default: 1693 // NOTE: this should never happen[tm] 1694 err := fmt.Errorf("%w: %s", errStatsICECandidateStateInvalid, state.String()) 1695 return StatsICECandidatePairState("Unknown"), err 1696 } 1697 } 1698 1699 const ( 1700 // StatsICECandidatePairStateFrozen means a check for this pair hasn't been 1701 // performed, and it can't yet be performed until some other check succeeds, 1702 // allowing this pair to unfreeze and move into the Waiting state. 1703 StatsICECandidatePairStateFrozen StatsICECandidatePairState = "frozen" 1704 1705 // StatsICECandidatePairStateWaiting means a check has not been performed for 1706 // this pair, and can be performed as soon as it is the highest-priority Waiting 1707 // pair on the check list. 1708 StatsICECandidatePairStateWaiting StatsICECandidatePairState = "waiting" 1709 1710 // StatsICECandidatePairStateInProgress means a check has been sent for this pair, 1711 // but the transaction is in progress. 1712 StatsICECandidatePairStateInProgress StatsICECandidatePairState = "in-progress" 1713 1714 // StatsICECandidatePairStateFailed means a check for this pair was already done 1715 // and failed, either never producing any response or producing an unrecoverable 1716 // failure response. 1717 StatsICECandidatePairStateFailed StatsICECandidatePairState = "failed" 1718 1719 // StatsICECandidatePairStateSucceeded means a check for this pair was already 1720 // done and produced a successful result. 1721 StatsICECandidatePairStateSucceeded StatsICECandidatePairState = "succeeded" 1722 ) 1723 1724 // ICECandidatePairStats contains ICE candidate pair statistics related 1725 // to the ICETransport objects. 1726 type ICECandidatePairStats struct { 1727 // Timestamp is the timestamp associated with this object. 1728 Timestamp StatsTimestamp `json:"timestamp"` 1729 1730 // Type is the object's StatsType 1731 Type StatsType `json:"type"` 1732 1733 // ID is a unique id that is associated with the component inspected to produce 1734 // this Stats object. Two Stats objects will have the same ID if they were produced 1735 // by inspecting the same underlying object. 1736 ID string `json:"id"` 1737 1738 // TransportID is a unique identifier that is associated to the object that 1739 // was inspected to produce the TransportStats associated with this candidate pair. 1740 TransportID string `json:"transportId"` 1741 1742 // LocalCandidateID is a unique identifier that is associated to the object 1743 // that was inspected to produce the ICECandidateStats for the local candidate 1744 // associated with this candidate pair. 1745 LocalCandidateID string `json:"localCandidateId"` 1746 1747 // RemoteCandidateID is a unique identifier that is associated to the object 1748 // that was inspected to produce the ICECandidateStats for the remote candidate 1749 // associated with this candidate pair. 1750 RemoteCandidateID string `json:"remoteCandidateId"` 1751 1752 // State represents the state of the checklist for the local and remote 1753 // candidates in a pair. 1754 State StatsICECandidatePairState `json:"state"` 1755 1756 // Nominated is true when this valid pair that should be used for media 1757 // if it is the highest-priority one amongst those whose nominated flag is set 1758 Nominated bool `json:"nominated"` 1759 1760 // PacketsSent represents the total number of packets sent on this candidate pair. 1761 PacketsSent uint32 `json:"packetsSent"` 1762 1763 // PacketsReceived represents the total number of packets received on this candidate pair. 1764 PacketsReceived uint32 `json:"packetsReceived"` 1765 1766 // BytesSent represents the total number of payload bytes sent on this candidate pair 1767 // not including headers or padding. 1768 BytesSent uint64 `json:"bytesSent"` 1769 1770 // BytesReceived represents the total number of payload bytes received on this candidate pair 1771 // not including headers or padding. 1772 BytesReceived uint64 `json:"bytesReceived"` 1773 1774 // LastPacketSentTimestamp represents the timestamp at which the last packet was 1775 // sent on this particular candidate pair, excluding STUN packets. 1776 LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"` 1777 1778 // LastPacketReceivedTimestamp represents the timestamp at which the last packet 1779 // was received on this particular candidate pair, excluding STUN packets. 1780 LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"` 1781 1782 // FirstRequestTimestamp represents the timestamp at which the first STUN request 1783 // was sent on this particular candidate pair. 1784 FirstRequestTimestamp StatsTimestamp `json:"firstRequestTimestamp"` 1785 1786 // LastRequestTimestamp represents the timestamp at which the last STUN request 1787 // was sent on this particular candidate pair. The average interval between two 1788 // consecutive connectivity checks sent can be calculated with 1789 // (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent. 1790 LastRequestTimestamp StatsTimestamp `json:"lastRequestTimestamp"` 1791 1792 // LastResponseTimestamp represents the timestamp at which the last STUN response 1793 // was received on this particular candidate pair. 1794 LastResponseTimestamp StatsTimestamp `json:"lastResponseTimestamp"` 1795 1796 // TotalRoundTripTime represents the sum of all round trip time measurements 1797 // in seconds since the beginning of the session, based on STUN connectivity 1798 // check responses (ResponsesReceived), including those that reply to requests 1799 // that are sent in order to verify consent. The average round trip time can 1800 // be computed from TotalRoundTripTime by dividing it by ResponsesReceived. 1801 TotalRoundTripTime float64 `json:"totalRoundTripTime"` 1802 1803 // CurrentRoundTripTime represents the latest round trip time measured in seconds, 1804 // computed from both STUN connectivity checks, including those that are sent 1805 // for consent verification. 1806 CurrentRoundTripTime float64 `json:"currentRoundTripTime"` 1807 1808 // AvailableOutgoingBitrate is calculated by the underlying congestion control 1809 // by combining the available bitrate for all the outgoing RTP streams using 1810 // this candidate pair. The bitrate measurement does not count the size of the 1811 // IP or other transport layers like TCP or UDP. It is similar to the TIAS defined 1812 // in RFC 3890, i.e., it is measured in bits per second and the bitrate is calculated 1813 // over a 1 second window. 1814 AvailableOutgoingBitrate float64 `json:"availableOutgoingBitrate"` 1815 1816 // AvailableIncomingBitrate is calculated by the underlying congestion control 1817 // by combining the available bitrate for all the incoming RTP streams using 1818 // this candidate pair. The bitrate measurement does not count the size of the 1819 // IP or other transport layers like TCP or UDP. It is similar to the TIAS defined 1820 // in RFC 3890, i.e., it is measured in bits per second and the bitrate is 1821 // calculated over a 1 second window. 1822 AvailableIncomingBitrate float64 `json:"availableIncomingBitrate"` 1823 1824 // CircuitBreakerTriggerCount represents the number of times the circuit breaker 1825 // is triggered for this particular 5-tuple, ceasing transmission. 1826 CircuitBreakerTriggerCount uint32 `json:"circuitBreakerTriggerCount"` 1827 1828 // RequestsReceived represents the total number of connectivity check requests 1829 // received (including retransmissions). It is impossible for the receiver to 1830 // tell whether the request was sent in order to check connectivity or check 1831 // consent, so all connectivity checks requests are counted here. 1832 RequestsReceived uint64 `json:"requestsReceived"` 1833 1834 // RequestsSent represents the total number of connectivity check requests 1835 // sent (not including retransmissions). 1836 RequestsSent uint64 `json:"requestsSent"` 1837 1838 // ResponsesReceived represents the total number of connectivity check responses received. 1839 ResponsesReceived uint64 `json:"responsesReceived"` 1840 1841 // ResponsesSent represents the total number of connectivity check responses sent. 1842 // Since we cannot distinguish connectivity check requests and consent requests, 1843 // all responses are counted. 1844 ResponsesSent uint64 `json:"responsesSent"` 1845 1846 // RetransmissionsReceived represents the total number of connectivity check 1847 // request retransmissions received. 1848 RetransmissionsReceived uint64 `json:"retransmissionsReceived"` 1849 1850 // RetransmissionsSent represents the total number of connectivity check 1851 // request retransmissions sent. 1852 RetransmissionsSent uint64 `json:"retransmissionsSent"` 1853 1854 // ConsentRequestsSent represents the total number of consent requests sent. 1855 ConsentRequestsSent uint64 `json:"consentRequestsSent"` 1856 1857 // ConsentExpiredTimestamp represents the timestamp at which the latest valid 1858 // STUN binding response expired. 1859 ConsentExpiredTimestamp StatsTimestamp `json:"consentExpiredTimestamp"` 1860 } 1861 1862 func (s ICECandidatePairStats) statsMarker() {} 1863 1864 func unmarshalICECandidatePairStats(b []byte) (ICECandidatePairStats, error) { 1865 var iceCandidatePairStats ICECandidatePairStats 1866 err := json.Unmarshal(b, &iceCandidatePairStats) 1867 if err != nil { 1868 return ICECandidatePairStats{}, fmt.Errorf("unmarshal ice candidate pair stats: %w", err) 1869 } 1870 return iceCandidatePairStats, nil 1871 } 1872 1873 // ICECandidateStats contains ICE candidate statistics related to the ICETransport objects. 1874 type ICECandidateStats struct { 1875 // Timestamp is the timestamp associated with this object. 1876 Timestamp StatsTimestamp `json:"timestamp"` 1877 1878 // Type is the object's StatsType 1879 Type StatsType `json:"type"` 1880 1881 // ID is a unique id that is associated with the component inspected to produce 1882 // this Stats object. Two Stats objects will have the same ID if they were produced 1883 // by inspecting the same underlying object. 1884 ID string `json:"id"` 1885 1886 // TransportID is a unique identifier that is associated to the object that 1887 // was inspected to produce the TransportStats associated with this candidate. 1888 TransportID string `json:"transportId"` 1889 1890 // NetworkType represents the type of network interface used by the base of a 1891 // local candidate (the address the ICE agent sends from). Only present for 1892 // local candidates; it's not possible to know what type of network interface 1893 // a remote candidate is using. 1894 // 1895 // Note: 1896 // This stat only tells you about the network interface used by the first "hop"; 1897 // it's possible that a connection will be bottlenecked by another type of network. 1898 // For example, when using Wi-Fi tethering, the networkType of the relevant candidate 1899 // would be "wifi", even when the next hop is over a cellular connection. 1900 // 1901 // DEPRECATED. Although it may still work in some browsers, the networkType property was deprecated for 1902 // preserving privacy. 1903 NetworkType NetworkType `json:"networkType,omitempty"` 1904 1905 // IP is the IP address of the candidate, allowing for IPv4 addresses and 1906 // IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed. 1907 IP string `json:"ip"` 1908 1909 // Port is the port number of the candidate. 1910 Port int32 `json:"port"` 1911 1912 // Protocol is one of udp and tcp. 1913 Protocol string `json:"protocol"` 1914 1915 // CandidateType is the "Type" field of the ICECandidate. 1916 CandidateType ICECandidateType `json:"candidateType"` 1917 1918 // Priority is the "Priority" field of the ICECandidate. 1919 Priority int32 `json:"priority"` 1920 1921 // URL is the URL of the TURN or STUN server indicated in the that translated 1922 // this IP address. It is the URL address surfaced in an PeerConnectionICEEvent. 1923 URL string `json:"url"` 1924 1925 // RelayProtocol is the protocol used by the endpoint to communicate with the 1926 // TURN server. This is only present for local candidates. Valid values for 1927 // the TURN URL protocol is one of udp, tcp, or tls. 1928 RelayProtocol string `json:"relayProtocol"` 1929 1930 // Deleted is true if the candidate has been deleted/freed. For host candidates, 1931 // this means that any network resources (typically a socket) associated with the 1932 // candidate have been released. For TURN candidates, this means the TURN allocation 1933 // is no longer active. 1934 // 1935 // Only defined for local candidates. For remote candidates, this property is not applicable. 1936 Deleted bool `json:"deleted"` 1937 } 1938 1939 func (s ICECandidateStats) statsMarker() {} 1940 1941 func unmarshalICECandidateStats(b []byte) (ICECandidateStats, error) { 1942 var iceCandidateStats ICECandidateStats 1943 err := json.Unmarshal(b, &iceCandidateStats) 1944 if err != nil { 1945 return ICECandidateStats{}, fmt.Errorf("unmarshal ice candidate stats: %w", err) 1946 } 1947 return iceCandidateStats, nil 1948 } 1949 1950 // CertificateStats contains information about a certificate used by an ICETransport. 1951 type CertificateStats struct { 1952 // Timestamp is the timestamp associated with this object. 1953 Timestamp StatsTimestamp `json:"timestamp"` 1954 1955 // Type is the object's StatsType 1956 Type StatsType `json:"type"` 1957 1958 // ID is a unique id that is associated with the component inspected to produce 1959 // this Stats object. Two Stats objects will have the same ID if they were produced 1960 // by inspecting the same underlying object. 1961 ID string `json:"id"` 1962 1963 // Fingerprint is the fingerprint of the certificate. 1964 Fingerprint string `json:"fingerprint"` 1965 1966 // FingerprintAlgorithm is the hash function used to compute the certificate fingerprint. For instance, "sha-256". 1967 FingerprintAlgorithm string `json:"fingerprintAlgorithm"` 1968 1969 // Base64Certificate is the DER-encoded base-64 representation of the certificate. 1970 Base64Certificate string `json:"base64Certificate"` 1971 1972 // IssuerCertificateID refers to the stats object that contains the next certificate 1973 // in the certificate chain. If the current certificate is at the end of the chain 1974 // (i.e. a self-signed certificate), this will not be set. 1975 IssuerCertificateID string `json:"issuerCertificateId"` 1976 } 1977 1978 func (s CertificateStats) statsMarker() {} 1979 1980 func unmarshalCertificateStats(b []byte) (CertificateStats, error) { 1981 var certificateStats CertificateStats 1982 err := json.Unmarshal(b, &certificateStats) 1983 if err != nil { 1984 return CertificateStats{}, fmt.Errorf("unmarshal certificate stats: %w", err) 1985 } 1986 return certificateStats, nil 1987 } 1988 1989 // SCTPTransportStats contains information about a certificate used by an SCTPTransport. 1990 type SCTPTransportStats struct { 1991 // Timestamp is the timestamp associated with this object. 1992 Timestamp StatsTimestamp `json:"timestamp"` 1993 1994 // Type is the object's StatsType 1995 Type StatsType `json:"type"` 1996 1997 // ID is a unique id that is associated with the component inspected to produce 1998 // this Stats object. Two Stats objects will have the same ID if they were produced 1999 // by inspecting the same underlying object. 2000 ID string `json:"id"` 2001 2002 // TransportID is the identifier of the object that was inspected to produce the 2003 // RTCTransportStats for the DTLSTransport and ICETransport supporting the SCTP transport. 2004 TransportID string `json:"transportId"` 2005 2006 // SmoothedRoundTripTime is the latest smoothed round-trip time value, corresponding to spinfo_srtt defined in [RFC6458] 2007 // but converted to seconds. If there has been no round-trip time measurements yet, this value is undefined. 2008 SmoothedRoundTripTime float64 `json:"smoothedRoundTripTime"` 2009 2010 // CongestionWindow is the latest congestion window, corresponding to spinfo_cwnd defined in [RFC6458]. 2011 CongestionWindow uint32 `json:"congestionWindow"` 2012 2013 // ReceiverWindow is the latest receiver window, corresponding to sstat_rwnd defined in [RFC6458]. 2014 ReceiverWindow uint32 `json:"receiverWindow"` 2015 2016 // MTU is the latest maximum transmission unit, corresponding to spinfo_mtu defined in [RFC6458]. 2017 MTU uint32 `json:"mtu"` 2018 2019 // UNACKData is the number of unacknowledged DATA chunks, corresponding to sstat_unackdata defined in [RFC6458]. 2020 UNACKData uint32 `json:"unackData"` 2021 2022 // BytesSent represents the total number of bytes sent on this SCTPTransport 2023 BytesSent uint64 `json:"bytesSent"` 2024 2025 // BytesReceived represents the total number of bytes received on this SCTPTransport 2026 BytesReceived uint64 `json:"bytesReceived"` 2027 } 2028 2029 func (s SCTPTransportStats) statsMarker() {} 2030 2031 func unmarshalSCTPTransportStats(b []byte) (SCTPTransportStats, error) { 2032 var sctpTransportStats SCTPTransportStats 2033 if err := json.Unmarshal(b, &sctpTransportStats); err != nil { 2034 return SCTPTransportStats{}, fmt.Errorf("unmarshal sctp transport stats: %w", err) 2035 } 2036 return sctpTransportStats, nil 2037 }