Overview
The stats package provides comprehensive statistics collection for WebRTC connections. It implements the WebRTC Statistics API, allowing you to monitor and measure various aspects of peer connections, RTP streams, ICE candidates, transports, and more.
Core Types
Stats Interface
The base interface for all statistics objects.
type Stats interface {
statsMarker ()
}
All statistics types implement this interface to identify them as valid stats objects.
StatsReport
A collection of stats objects indexed by their unique identifiers.
type StatsReport map [ string ] Stats
Usage Example
pc , _ := webrtc . NewPeerConnection ( webrtc . Configuration {})
// Get statistics report
stats := pc . GetStats ()
// Iterate through all stats
for id , stat := range stats {
switch s := stat .( type ) {
case webrtc . InboundRTPStreamStats :
fmt . Printf ( "Inbound RTP: %d packets received \n " , s . PacketsReceived )
case webrtc . ICECandidatePairStats :
fmt . Printf ( "Candidate pair: %s \n " , s . State )
}
}
StatsTimestamp
A timestamp represented as floating point milliseconds since epoch.
type StatsTimestamp float64
Converts the timestamp to a Go time.Time value
Example
timestamp := stats . Timestamp
t := timestamp . Time ()
fmt . Printf ( "Stats captured at: %s \n " , t . Format ( time . RFC3339 ))
Statistics Types
StatsType
Indicates the type of statistics object.
Constants
Used by CodecStats (“codec”)
Used by InboundRTPStreamStats (“inbound-rtp”)
Used by OutboundRTPStreamStats (“outbound-rtp”)
StatsTypeRemoteInboundRTP
Used by RemoteInboundRTPStreamStats (“remote-inbound-rtp”)
StatsTypeRemoteOutboundRTP
Used by RemoteOutboundRTPStreamStats (“remote-outbound-rtp”)
Used by RTPContributingSourceStats (“csrc”)
Used by AudioSourceStats or VideoSourceStats (“media-source”)
Used by AudioPlayoutStats (“media-playout”)
Used by PeerConnectionStats (“peer-connection”)
Used by DataChannelStats (“data-channel”)
Used by TransportStats (“transport”)
Used by ICECandidatePairStats (“candidate-pair”)
Used by ICECandidateStats for local candidates (“local-candidate”)
Used by ICECandidateStats for remote candidates (“remote-candidate”)
Used by CertificateStats (“certificate”)
Used by SCTPTransportStats (“sctp-transport”)
RTP Stream Statistics
InboundRTPStreamStats
Statistics for an inbound RTP stream currently being received.
type InboundRTPStreamStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
SSRC SSRC
Kind string
Mid string
// Transport and codec
TransportID string
CodecID string
// Packet metrics
PacketsReceived uint32
PacketsLost int32
PacketsDiscarded uint32
PacketsRepaired uint32
PacketsDuplicated uint32
PacketsFailedDecryption uint32
// Byte metrics
BytesReceived uint64
HeaderBytesReceived uint64
// Quality metrics
Jitter float64
// RTCP feedback
FIRCount uint32
PLICount uint32
NACKCount uint32
SLICount uint32
// Jitter buffer
JitterBufferDelay float64
JitterBufferTargetDelay float64
JitterBufferEmittedCount uint64
JitterBufferMinimumDelay float64
// Video-specific (when Kind == "video")
FramesReceived uint32
FramesDecoded uint32
KeyFramesDecoded uint32
FramesRendered uint32
FramesDropped uint32
FrameWidth uint32
FrameHeight uint32
TotalDecodeTime float64
TotalInterFrameDelay float64
TotalSquaredInterFrameDelay float64
QPSum uint64
PauseCount uint32
TotalPausesDuration float64
FreezeCount uint32
TotalFreezesDuration float64
PowerEfficientDecoder bool
DecoderImplementation string
// Audio-specific (when Kind == "audio")
TotalSamplesReceived uint64
ConcealedSamples uint64
SilentConcealedSamples uint64
ConcealmentEvents uint64
InsertedSamplesForDeceleration uint64
RemovedSamplesForAcceleration uint64
AudioLevel float64
TotalAudioEnergy float64
TotalSamplesDuration float64
// Processing
TotalProcessingDelay float64
// Burst and gap metrics
BurstPacketsLost uint32
BurstPacketsDiscarded uint32
BurstLossCount uint32
BurstDiscardCount uint32
BurstLossRate float64
BurstDiscardRate float64
GapLossRate float64
GapDiscardRate float64
// FEC
FECPacketsReceived uint32
FECPacketsDiscarded uint64
// References
TrackID string
ReceiverID string
RemoteID string
// Timing
LastPacketReceivedTimestamp StatsTimestamp
AverageRTCPInterval float64
// DSCP
PerDSCPPacketsReceived map [ string ] uint32
}
Monitoring Inbound Video Quality
Monitoring Audio Quality
stats := pc . GetStats ()
for _ , stat := range stats {
if inbound , ok := stat .( webrtc . InboundRTPStreamStats ); ok && inbound . Kind == "video" {
fmt . Printf ( "Video Stats: \n " )
fmt . Printf ( " Packets: %d received, %d lost \n " ,
inbound . PacketsReceived , inbound . PacketsLost )
fmt . Printf ( " Frames: %d decoded, %d dropped \n " ,
inbound . FramesDecoded , inbound . FramesDropped )
fmt . Printf ( " Resolution: %d x %d \n " ,
inbound . FrameWidth , inbound . FrameHeight )
fmt . Printf ( " Jitter: %.3f seconds \n " , inbound . Jitter )
// Calculate packet loss rate
total := uint32 ( int32 ( inbound . PacketsReceived ) + inbound . PacketsLost )
if total > 0 {
lossRate := float64 ( inbound . PacketsLost ) / float64 ( total ) * 100
fmt . Printf ( " Loss Rate: %.2f%% \n " , lossRate )
}
}
}
OutboundRTPStreamStats
Statistics for an outbound RTP stream currently being sent.
type OutboundRTPStreamStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
SSRC SSRC
Kind string
Mid string
Rid string
// Transport and codec
TransportID string
CodecID string
MediaSourceID string
// Packet metrics
PacketsSent uint32
PacketsDiscardedOnSend uint32
RetransmittedPacketsSent uint64
// Byte metrics
BytesSent uint64
HeaderBytesSent uint64
RetransmittedBytesSent uint64
BytesDiscardedOnSend uint64
// RTCP feedback
FIRCount uint32
PLICount uint32
NACKCount uint32
SLICount uint32
// Video-specific (when Kind == "video")
FramesSent uint32
HugeFramesSent uint32
FramesEncoded uint32
KeyFramesEncoded uint32
FrameWidth uint32
FrameHeight uint32
FramesPerSecond float64
QPSum uint64
TotalEncodeTime float64
QualityLimitationReason QualityLimitationReason
QualityLimitationDurations map [ string ] float64
QualityLimitationResolutionChanges uint32
PowerEfficientEncoder bool
EncoderImplementation string
ScalabilityMode string
// Bitrate
TargetBitrate float64
TotalEncodedBytesTarget uint64
// Timing
TotalPacketSendDelay float64
LastPacketSentTimestamp StatsTimestamp
AverageRTCPInterval float64
// FEC
FECPacketsSent uint32
// References
TrackID string
SenderID string
RemoteID string
// State
Active bool
// DSCP
PerDSCPPacketsSent map [ string ] uint32
}
Show QualityLimitationReason
Indicates why video resolution/framerate is limited:
QualityLimitationReasonNone - Not limited
QualityLimitationReasonCPU - Limited due to CPU load
QualityLimitationReasonBandwidth - Limited due to bandwidth
QualityLimitationReasonOther - Limited for other reasons
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if outbound , ok := stat .( webrtc . OutboundRTPStreamStats ); ok && outbound . Kind == "video" {
fmt . Printf ( "Outbound Video Stats: \n " )
fmt . Printf ( " Packets sent: %d \n " , outbound . PacketsSent )
fmt . Printf ( " Frames encoded: %d (key frames: %d ) \n " ,
outbound . FramesEncoded , outbound . KeyFramesEncoded )
fmt . Printf ( " Target bitrate: %.0f bps \n " , outbound . TargetBitrate )
fmt . Printf ( " Quality limitation: %s \n " , outbound . QualityLimitationReason )
// Calculate average encode time
if outbound . FramesEncoded > 0 {
avgEncodeTime := outbound . TotalEncodeTime / float64 ( outbound . FramesEncoded )
fmt . Printf ( " Avg encode time: %.2f ms \n " , avgEncodeTime * 1000 )
}
}
}
RemoteInboundRTPStreamStats
Statistics for the remote endpoint’s inbound RTP stream, measured at the remote endpoint and reported via RTCP.
type RemoteInboundRTPStreamStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
SSRC SSRC
Kind string
TransportID string
CodecID string
// Packet metrics
PacketsReceived uint32
PacketsLost int32
PacketsDiscarded uint32
PacketsRepaired uint32
// Quality metrics
Jitter float64
// RTCP feedback
FIRCount uint32
PLICount uint32
NACKCount uint32
SLICount uint32
QPSum uint64
// Burst and gap metrics
BurstPacketsLost uint32
BurstPacketsDiscarded uint32
BurstLossCount uint32
BurstDiscardCount uint32
BurstLossRate float64
BurstDiscardRate float64
GapLossRate float64
GapDiscardRate float64
// Round trip time
RoundTripTime float64
TotalRoundTripTime float64
FractionLost float64
RoundTripTimeMeasurements uint64
// Reference
LocalID string
}
RemoteOutboundRTPStreamStats
Statistics for the remote endpoint’s outbound RTP stream, measured at the remote endpoint and reported via RTCP.
type RemoteOutboundRTPStreamStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
SSRC SSRC
Kind string
TransportID string
CodecID string
// Packet metrics
PacketsSent uint32
PacketsDiscardedOnSend uint32
FECPacketsSent uint32
// Byte metrics
BytesSent uint64
BytesDiscardedOnSend uint64
// RTCP feedback
FIRCount uint32
PLICount uint32
NACKCount uint32
SLICount uint32
QPSum uint64
// Round trip time
RoundTripTime float64
TotalRoundTripTime float64
RoundTripTimeMeasurements uint64
// References
LocalID string
RemoteTimestamp StatsTimestamp
ReportsSent uint64
}
Codec Statistics
CodecStats
Statistics for a codec currently being used by RTP streams.
type CodecStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
PayloadType PayloadType
CodecType CodecType
TransportID string
MimeType string
ClockRate uint32
Channels uint8
SDPFmtpLine string
Implementation string
}
Either CodecTypeEncode or CodecTypeDecode
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if codec , ok := stat .( webrtc . CodecStats ); ok {
fmt . Printf ( "Codec: %s \n " , codec . MimeType )
fmt . Printf ( " Payload Type: %d \n " , codec . PayloadType )
fmt . Printf ( " Clock Rate: %d Hz \n " , codec . ClockRate )
fmt . Printf ( " Type: %s \n " , codec . CodecType )
if codec . Channels > 0 {
fmt . Printf ( " Channels: %d \n " , codec . Channels )
}
}
}
AudioSourceStats
Statistics for an audio track attached to sender(s).
type AudioSourceStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TrackIdentifier string
Kind string
AudioLevel float64
TotalAudioEnergy float64
TotalSamplesDuration float64
EchoReturnLoss float64
EchoReturnLossEnhancement float64
DroppedSamplesDuration float64
DroppedSamplesEvents uint64
TotalCaptureDelay float64
TotalSamplesCaptured uint64
}
VideoSourceStats
Statistics for a video track attached to sender(s).
type VideoSourceStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TrackIdentifier string
Kind string
Width uint32
Height uint32
Frames uint32
FramesPerSecond float64
}
Example
stats := pc . GetStats ()
for _ , stat := range stats {
switch source := stat .( type ) {
case webrtc . AudioSourceStats :
fmt . Printf ( "Audio Source: %s \n " , source . TrackIdentifier )
fmt . Printf ( " Audio Level: %.2f \n " , source . AudioLevel )
fmt . Printf ( " Samples Captured: %d \n " , source . TotalSamplesCaptured )
case webrtc . VideoSourceStats :
fmt . Printf ( "Video Source: %s \n " , source . TrackIdentifier )
fmt . Printf ( " Resolution: %d x %d \n " , source . Width , source . Height )
fmt . Printf ( " FPS: %.1f \n " , source . FramesPerSecond )
}
}
ICE Statistics
ICECandidatePairStats
Statistics for an ICE candidate pair.
type ICECandidatePairStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TransportID string
LocalCandidateID string
RemoteCandidateID string
State StatsICECandidatePairState
Nominated bool
// Packet metrics
PacketsSent uint32
PacketsReceived uint32
PacketsDiscardedOnSend uint32
// Byte metrics
BytesSent uint64
BytesReceived uint64
BytesDiscardedOnSend uint32
// Timing
LastPacketSentTimestamp StatsTimestamp
LastPacketReceivedTimestamp StatsTimestamp
FirstRequestTimestamp StatsTimestamp
LastRequestTimestamp StatsTimestamp
FirstResponseTimestamp StatsTimestamp
LastResponseTimestamp StatsTimestamp
FirstRequestReceivedTimestamp StatsTimestamp
LastRequestReceivedTimestamp StatsTimestamp
// Round trip time
TotalRoundTripTime float64
CurrentRoundTripTime float64
// Bandwidth
AvailableOutgoingBitrate float64
AvailableIncomingBitrate float64
// STUN metrics
RequestsReceived uint64
RequestsSent uint64
ResponsesReceived uint64
ResponsesSent uint64
RetransmissionsReceived uint64
RetransmissionsSent uint64
ConsentRequestsSent uint64
ConsentExpiredTimestamp StatsTimestamp
// Circuit breaker
CircuitBreakerTriggerCount uint32
}
Show StatsICECandidatePairState Values
StatsICECandidatePairStateFrozen - Check hasn’t been performed yet
StatsICECandidatePairStateWaiting - Waiting to perform check
StatsICECandidatePairStateInProgress - Check in progress
StatsICECandidatePairStateFailed - Check failed
StatsICECandidatePairStateSucceeded - Check succeeded
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if pair , ok := stat .( webrtc . ICECandidatePairStats ); ok && pair . Nominated {
fmt . Printf ( "Active Candidate Pair: \n " )
fmt . Printf ( " State: %s \n " , pair . State )
fmt . Printf ( " RTT: %.3f ms \n " , pair . CurrentRoundTripTime * 1000 )
fmt . Printf ( " Bytes sent: %d , received: %d \n " ,
pair . BytesSent , pair . BytesReceived )
fmt . Printf ( " Available bitrate: out= %.0f , in= %.0f bps \n " ,
pair . AvailableOutgoingBitrate , pair . AvailableIncomingBitrate )
}
}
ICECandidateStats
Statistics for an ICE candidate.
type ICECandidateStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TransportID string
NetworkType string // Deprecated
IP string
Port int32
Protocol string
CandidateType ICECandidateType
Priority int32
URL string
RelayProtocol string
Deleted bool
}
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if candidate , ok := stat .( webrtc . ICECandidateStats ); ok {
fmt . Printf ( "Candidate %s : \n " , candidate . ID )
fmt . Printf ( " Type: %s \n " , candidate . CandidateType )
fmt . Printf ( " Address: %s : %d \n " , candidate . IP , candidate . Port )
fmt . Printf ( " Protocol: %s \n " , candidate . Protocol )
if candidate . RelayProtocol != "" {
fmt . Printf ( " Relay Protocol: %s \n " , candidate . RelayProtocol )
}
}
}
Transport Statistics
TransportStats
Statistics for the ICE/DTLS transport.
type TransportStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
PacketsSent uint32
PacketsReceived uint32
BytesSent uint64
BytesReceived uint64
RTCPTransportStatsID string
ICERole ICERole
DTLSState DTLSTransportState
ICEState ICETransportState
SelectedCandidatePairID string
LocalCertificateID string
RemoteCertificateID string
DTLSCipher string
SRTPCipher string
}
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if transport , ok := stat .( webrtc . TransportStats ); ok {
fmt . Printf ( "Transport: \n " )
fmt . Printf ( " ICE State: %s \n " , transport . ICEState )
fmt . Printf ( " DTLS State: %s \n " , transport . DTLSState )
fmt . Printf ( " DTLS Cipher: %s \n " , transport . DTLSCipher )
fmt . Printf ( " SRTP Cipher: %s \n " , transport . SRTPCipher )
fmt . Printf ( " Total bytes: sent= %d , received= %d \n " ,
transport . BytesSent , transport . BytesReceived )
}
}
CertificateStats
Statistics for a certificate used by an ICE transport.
type CertificateStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
Fingerprint string
FingerprintAlgorithm string
Base64Certificate string
IssuerCertificateID string
}
Data Channel Statistics
DataChannelStats
Statistics for a data channel.
type DataChannelStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
Label string
Protocol string
DataChannelIdentifier int32
TransportID string
State DataChannelState
MessagesSent uint32
BytesSent uint64
MessagesReceived uint32
BytesReceived uint64
}
Example
stats := pc . GetStats ()
for _ , stat := range stats {
if dc , ok := stat .( webrtc . DataChannelStats ); ok {
fmt . Printf ( "DataChannel ' %s ': \n " , dc . Label )
fmt . Printf ( " State: %s \n " , dc . State )
fmt . Printf ( " Messages: sent= %d , received= %d \n " ,
dc . MessagesSent , dc . MessagesReceived )
fmt . Printf ( " Bytes: sent= %d , received= %d \n " ,
dc . BytesSent , dc . BytesReceived )
}
}
SCTPTransportStats
Statistics for the SCTP transport used by data channels.
type SCTPTransportStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TransportID string
SmoothedRoundTripTime float64
CongestionWindow uint32
ReceiverWindow uint32
MTU uint32
UNACKData uint32
BytesSent uint64
BytesReceived uint64
}
PeerConnection Statistics
PeerConnectionStats
Statistics for the overall peer connection.
type PeerConnectionStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
DataChannelsOpened uint32
DataChannelsClosed uint32
DataChannelsRequested uint32
DataChannelsAccepted uint32
}
Additional Statistics Types
AudioPlayoutStats
Statistics for audio playout path.
type AudioPlayoutStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
Kind string
SynthesizedSamplesDuration float64
SynthesizedSamplesEvents uint64
TotalSamplesDuration float64
TotalPlayoutDelay float64
TotalSamplesCount uint64
}
RTPContributingSourceStats
Statistics for a contributing source (CSRC).
type RTPContributingSourceStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
ContributorSSRC SSRC
InboundRTPStreamID string
PacketsContributedTo uint32
AudioLevel float64
}
Sender and Receiver Statistics
AudioSenderStats
VideoSenderStats
AudioReceiverStats
VideoReceiverStats
type AudioSenderStats struct {
Timestamp StatsTimestamp
Type StatsType
ID string
TrackIdentifier string
RemoteSource bool
Ended bool
Kind string
AudioLevel float64
TotalAudioEnergy float64
VoiceActivityFlag bool
TotalSamplesDuration float64
EchoReturnLoss float64
EchoReturnLossEnhancement float64
TotalSamplesSent uint64
}
Utility Functions
UnmarshalStatsJSON
Unmarshals a Stats object from JSON.
func UnmarshalStatsJSON ( b [] byte ) ( Stats , error )
Parameters
JSON-encoded statistics object
Returns
The unmarshaled statistics object (specific type based on the “type” field)
Error if unmarshaling fails or type is unknown
Example
jsonData := [] byte ( `{
"type": "inbound-rtp",
"id": "RTCInboundRTPVideoStream_12345",
"timestamp": 1234567890.0,
"ssrc": 12345,
"kind": "video",
"packetsReceived": 1000,
"bytesReceived": 500000
}` )
stat , err := webrtc . UnmarshalStatsJSON ( jsonData )
if err != nil {
log . Fatal ( err )
}
if inbound , ok := stat .( webrtc . InboundRTPStreamStats ); ok {
fmt . Printf ( "Received %d packets \n " , inbound . PacketsReceived )
}
Common Patterns
Monitoring Connection Quality
func monitorConnectionQuality ( pc * webrtc . PeerConnection ) {
ticker := time . NewTicker ( 1 * time . Second )
defer ticker . Stop ()
for range ticker . C {
stats := pc . GetStats ()
// Find active candidate pair
for _ , stat := range stats {
if pair , ok := stat .( webrtc . ICECandidatePairStats ); ok && pair . Nominated {
fmt . Printf ( "RTT: %.0f ms, Bitrate: %.0f kbps \n " ,
pair . CurrentRoundTripTime * 1000 ,
pair . AvailableOutgoingBitrate / 1000 )
}
}
// Check video quality
for _ , stat := range stats {
if inbound , ok := stat .( webrtc . InboundRTPStreamStats ); ok && inbound . Kind == "video" {
if inbound . PacketsReceived > 0 {
total := uint32 ( int32 ( inbound . PacketsReceived ) + inbound . PacketsLost )
lossRate := float64 ( inbound . PacketsLost ) / float64 ( total ) * 100
fmt . Printf ( "Video Loss Rate: %.2f%% \n " , lossRate )
}
}
}
}
}
Exporting Stats to JSON
func exportStats ( pc * webrtc . PeerConnection ) ([] byte , error ) {
stats := pc . GetStats ()
return json . MarshalIndent ( stats , "" , " " )
}
Calculating Bitrates
type BitrateCalculator struct {
lastStats webrtc . InboundRTPStreamStats
lastTimestamp time . Time
}
func ( bc * BitrateCalculator ) Calculate ( current webrtc . InboundRTPStreamStats ) float64 {
now := current . Timestamp . Time ()
if bc . lastTimestamp . IsZero () {
bc . lastStats = current
bc . lastTimestamp = now
return 0
}
deltaBytes := current . BytesReceived - bc . lastStats . BytesReceived
deltaTime := now . Sub ( bc . lastTimestamp ). Seconds ()
bc . lastStats = current
bc . lastTimestamp = now
if deltaTime > 0 {
return float64 ( deltaBytes ) * 8 / deltaTime // bits per second
}
return 0
}
See Also