The Report interceptors generate standard RTCP Sender Reports (SR) and Receiver Reports (RR) that provide statistics about RTP stream quality and synchronization.
Overview
Report interceptors provide:
Sender Reports (SR) : Statistics about outgoing streams (packet count, byte count, timestamps)
Receiver Reports (RR) : Statistics about incoming streams (packet loss, jitter, delay)
Synchronization : NTP timestamps for media synchronization
Periodic feedback : Automatic report generation at configurable intervals
Sender Interceptor
Generates RTCP Sender Reports for outgoing RTP streams.
Basic Usage
import (
" time "
" github.com/pion/interceptor "
" github.com/pion/interceptor/pkg/report "
)
// Create sender interceptor
senderFactory , err := report . NewSenderInterceptor (
report . SenderInterval ( 1 * time . Second ),
)
if err != nil {
panic ( err )
}
// Register with interceptor registry
m := & interceptor . Registry {}
m . Add ( senderFactory )
Configuration Options
Sets how often to send sender reports. senderFactory , err := report . NewSenderInterceptor (
report . SenderInterval ( 1 * time . Second ), // Default: 1 second
)
Uses the latest packet for timestamp calculations, even if it appears out of order. senderFactory , err := report . NewSenderInterceptor (
report . SenderUseLatestPacket (),
)
SenderLog / WithSenderLoggerFactory
Configure logging for debugging. senderFactory , err := report . NewSenderInterceptor (
report . WithSenderLoggerFactory ( loggerFactory ),
)
Sender Report Contents
Sender Reports include:
type SenderReport struct {
// SSRC of the sender
SSRC uint32
// NTP timestamp (wall clock time)
NTPTime uint64
// RTP timestamp
RTPTime uint32
// Sender's packet count
PacketCount uint32
// Sender's byte count
OctetCount uint32
}
Receiver Interceptor
Generates RTCP Receiver Reports for incoming RTP streams.
Basic Usage
// Create receiver interceptor
receiverFactory , err := report . NewReceiverInterceptor (
report . ReceiverInterval ( 1 * time . Second ),
)
if err != nil {
panic ( err )
}
m . Add ( receiverFactory )
Configuration Options
Sets how often to send receiver reports. receiverFactory , err := report . NewReceiverInterceptor (
report . ReceiverInterval ( 1 * time . Second ), // Default: 1 second
)
ReceiverLog / WithReceiverLoggerFactory
Configure logging for debugging. receiverFactory , err := report . NewReceiverInterceptor (
report . WithReceiverLoggerFactory ( loggerFactory ),
)
Receiver Report Contents
Receiver Reports include:
type ReceptionReport struct {
// SSRC of the source
SSRC uint32
// Fraction of packets lost since last report (0-255)
FractionLost uint8
// Total number of packets lost
TotalLost uint32
// Highest sequence number received
LastSequenceNumber uint32
// Interarrival jitter
Jitter uint32
// Last SR timestamp
LastSenderReport uint32
// Delay since last SR (in 1/65536 seconds)
Delay uint32
}
Complete Example
package main
import (
" log "
" time "
" github.com/pion/interceptor "
" github.com/pion/interceptor/pkg/report "
" github.com/pion/logging "
" github.com/pion/webrtc/v4 "
)
func main () {
// Create logger factory
loggerFactory := logging . NewDefaultLoggerFactory ()
// Create interceptor registry
i := & interceptor . Registry {}
// Setup sender reports
senderFactory , err := report . NewSenderInterceptor (
report . SenderInterval ( 1 * time . Second ),
report . WithSenderLoggerFactory ( loggerFactory ),
)
if err != nil {
panic ( err )
}
i . Add ( senderFactory )
// Setup receiver reports
receiverFactory , err := report . NewReceiverInterceptor (
report . ReceiverInterval ( 1 * time . Second ),
report . WithReceiverLoggerFactory ( loggerFactory ),
)
if err != nil {
panic ( err )
}
i . Add ( receiverFactory )
// Create media engine and API
m := & webrtc . MediaEngine {}
if err := m . RegisterDefaultCodecs (); err != nil {
panic ( err )
}
api := webrtc . NewAPI (
webrtc . WithMediaEngine ( m ),
webrtc . WithInterceptorRegistry ( i ),
)
// Create peer connection
peerConnection , err := api . NewPeerConnection ( webrtc . Configuration {})
if err != nil {
panic ( err )
}
defer peerConnection . Close ()
log . Println ( "Reports configured successfully" )
}
How Reports Work
Sender Report Generation
Packet Tracking : Monitors outgoing RTP packets
Statistics Collection : Counts packets and bytes
Timestamp Mapping : Records NTP to RTP timestamp correlation
Report Creation : Generates SR with current statistics
Transmission : Sends SR via RTCP at configured interval
Receiver Report Generation
Packet Monitoring : Tracks incoming RTP packets
Loss Calculation : Detects missing sequence numbers
Jitter Estimation : Calculates interarrival jitter
SR Processing : Records timestamps from received sender reports
RR Creation : Generates receiver report with statistics
Transmission : Sends RR via RTCP
Understanding Jitter
Jitter represents the variance in packet arrival times:
// Jitter calculation (simplified)
delta := arrivalTime - expectedArrivalTime
jitter := ( 15 * jitter + abs ( delta )) / 16 // EWMA with α=1/16
Lower jitter values indicate more consistent packet arrival times. High jitter can cause playback issues.
Using with Stats
Combine with the Stats interceptor for more detailed metrics:
import (
" github.com/pion/interceptor/pkg/report "
" github.com/pion/interceptor/pkg/stats "
)
// Add both report and stats interceptors
reportFactory , _ := report . NewSenderInterceptor ()
i . Add ( reportFactory )
statsFactory , _ := stats . NewInterceptor ()
i . Add ( statsFactory )
// Reports provide standard RTCP feedback
// Stats provide detailed stream metrics
Monitoring Reports
Process received reports to monitor stream quality:
// Handle incoming RTCP packets
peerConnection . OnRTCP ( func ( packets [] rtcp . Packet ) {
for _ , pkt := range packets {
switch p := pkt .( type ) {
case * rtcp . SenderReport :
log . Printf ( "Sender Report from SSRC %d :" , p . SSRC )
log . Printf ( " Packets: %d " , p . PacketCount )
log . Printf ( " Bytes: %d " , p . OctetCount )
log . Printf ( " NTP: %d , RTP: %d " , p . NTPTime , p . RTPTime )
case * rtcp . ReceiverReport :
for _ , rr := range p . Reports {
log . Printf ( "Receiver Report for SSRC %d :" , rr . SSRC )
log . Printf ( " Lost: %d ( %.2f%% )" ,
rr . TotalLost ,
float64 ( rr . FractionLost ) / 256 * 100 )
log . Printf ( " Jitter: %d " , rr . Jitter )
}
}
}
})
Calculating RTT
Use SR and RR to calculate round-trip time:
// When receiving RR with LastSenderReport (LSR) and Delay (DLSR)
roundTripTime := currentNTPTime - LSR - DLSR
// Convert to milliseconds
rttMs := float64 ( roundTripTime ) * 1000.0 / 65536.0
Best Practices
Report Interval : 1 second is standard, adjust based on network conditions
Compound RTCP : Reports are often sent with other RTCP packets
Bandwidth Limits : RTCP should use ~5% of session bandwidth
Monitor Regularly : Check reports for quality issues
Synchronization : Use NTP timestamps for A/V sync
RTCP bandwidth is automatically managed by the WebRTC implementation to comply with RFC 3550.
Report Intervals
Standard Intervals
// Voice calls - frequent reports
report . SenderInterval ( 1 * time . Second )
// Video conferencing - standard
report . SenderInterval ( 1 * time . Second )
// Broadcasting - less frequent
report . SenderInterval ( 5 * time . Second )
// Low bandwidth - reduced frequency
report . SenderInterval ( 10 * time . Second )
Dynamic Adjustment
Adjust intervals based on conditions:
// Monitor packet loss
if packetLossRate > 0.05 {
// Increase report frequency during issues
senderFactory , _ = report . NewSenderInterceptor (
report . SenderInterval ( 500 * time . Millisecond ),
)
}
Troubleshooting
Check:
Interceptor is properly registered
RTP packets are flowing
RTCP is not blocked by firewall
Report interval is not too long
Ensure:
Clock synchronization is working
Timestamps are monotonic
Network conditions are stable
High packet loss reported
Investigate:
Network congestion
Bandwidth constraints
Packet reordering
Firewall dropping packets
Stats - More detailed stream statistics
NACK - Request retransmission of lost packets
TWCC - Transport-wide congestion feedback