The FlexFEC interceptor implements forward error correction (FEC) to recover lost packets without retransmission. It generates redundant FEC packets that can be used to reconstruct missing media packets.
Overview
FlexFEC provides:
Proactive recovery : Repairs packet loss without round-trip delay
Flexible protection : Configurable redundancy levels
FlexFEC-03 support : Compatible with Chrome and other WebRTC implementations
Automatic generation : Seamlessly creates FEC packets
Basic Usage
import (
" github.com/pion/interceptor "
" github.com/pion/interceptor/pkg/flexfec "
)
// Create FlexFEC interceptor
fecFactory , err := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ), // Protect every 5 media packets
flexfec . NumFECPackets ( 2 ), // Generate 2 FEC packets
)
if err != nil {
panic ( err )
}
// Register with interceptor registry
m := & interceptor . Registry {}
m . Add ( fecFactory )
Configuration Options
Sets how many media packets to accumulate before generating FEC packets:
fecFactory , err := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ), // Default: 5
)
Smaller values provide more frequent protection but higher overhead. Typical values: 5-10 packets.
NumFECPackets
Sets how many FEC packets to generate for each block of media packets:
fecFactory , err := flexfec . NewFecInterceptor (
flexfec . NumFECPackets ( 2 ), // Default: 2
)
Protection levels:
1 FEC packet: Can recover 1 lost media packet (20% overhead for 5 media)
2 FEC packets: Can recover 2 lost media packets (40% overhead for 5 media)
3 FEC packets: Can recover 3 lost media packets (60% overhead for 5 media)
FECEncoderFactory
Provide a custom FEC encoder implementation:
fecFactory , err := flexfec . NewFecInterceptor (
flexfec . FECEncoderFactory ( customFactory ),
)
Complete Example
package main
import (
" log "
" github.com/pion/interceptor "
" github.com/pion/interceptor/pkg/flexfec "
" github.com/pion/webrtc/v4 "
)
func main () {
// Create media engine
m := & webrtc . MediaEngine {}
if err := m . RegisterDefaultCodecs (); err != nil {
panic ( err )
}
// Create interceptor registry
i := & interceptor . Registry {}
// Configure FlexFEC
// Protect 5 media packets with 2 FEC packets
// This provides ~40% overhead and can recover up to 2 lost packets
fecFactory , err := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ),
flexfec . NumFECPackets ( 2 ),
)
if err != nil {
panic ( err )
}
i . Add ( fecFactory )
// Create API with FEC support
api := webrtc . NewAPI (
webrtc . WithMediaEngine ( m ),
webrtc . WithInterceptorRegistry ( i ),
)
// Create peer connection
pc , err := api . NewPeerConnection ( webrtc . Configuration {})
if err != nil {
panic ( err )
}
defer pc . Close ()
// Add video track with FEC parameters
track , err := webrtc . NewTrackLocalStaticSample (
webrtc . RTPCodecCapability { MimeType : webrtc . MimeTypeVP8 },
"video" ,
"pion" ,
)
if err != nil {
panic ( err )
}
_ , err = pc . AddTrack ( track )
if err != nil {
panic ( err )
}
log . Println ( "FlexFEC configured successfully" )
}
How FlexFEC Works
Encoding Process
Accumulate : Collect N media packets
Generate : Create K FEC packets using XOR-based coding
Transmit : Send both media and FEC packets
Decode : Receiver uses FEC to recover lost media packets
Media packets: [P1] [P2] [P3] [P4] [P5]
| | | | |
v v v v v
XOR based encoding
|
v
FEC packets: [F1] [F2]
Recovery Capability
// Example: 5 media + 2 FEC packets
// Can recover:
// - Any 1 lost packet: ✓
// - Any 2 lost packets: ✓
// - 3+ lost packets: ✗ (not enough FEC)
// Lost packets ≤ FEC packets: Recoverable
// Lost packets > FEC packets: Unrecoverable
FlexFEC can only recover up to K lost packets per block, where K is the number of FEC packets generated.
Protection Levels
Light Protection (Low Overhead)
// 10 media + 1 FEC = 10% overhead
// Can recover 1 lost packet per 10
fecFactory , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 10 ),
flexfec . NumFECPackets ( 1 ),
)
Use for: Good networks with occasional loss (< 5%)
Medium Protection (Balanced)
// 5 media + 2 FEC = 40% overhead
// Can recover 2 lost packets per 5
fecFactory , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ),
flexfec . NumFECPackets ( 2 ),
)
Use for: Typical networks with moderate loss (5-10%)
Heavy Protection (High Overhead)
// 3 media + 2 FEC = 67% overhead
// Can recover 2 lost packets per 3
fecFactory , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 3 ),
flexfec . NumFECPackets ( 2 ),
)
Use for: Poor networks with high loss (10-20%)
Calculating Overhead
func calculateOverhead ( mediaPackets , fecPackets uint32 ) float64 {
return float64 ( fecPackets ) / float64 ( mediaPackets ) * 100
}
// Examples:
overhead := calculateOverhead ( 5 , 2 ) // 40%
overhead := calculateOverhead ( 10 , 1 ) // 10%
overhead := calculateOverhead ( 3 , 2 ) // 67%
SDP Configuration
FlexFEC requires proper SDP negotiation:
m=video 9 UDP/TLS/RTP/SAVPF 96 100
a=rtpmap:96 VP8/90000
a=rtpmap:100 flexfec-03/90000
a=fmtp:100 repair-window=10000000
Pion handles this automatically when FlexFEC is configured.
Integration Patterns
With NACK
Combine FEC and retransmission for robust recovery:
import (
" github.com/pion/interceptor/pkg/flexfec "
" github.com/pion/interceptor/pkg/nack "
)
// Add FlexFEC for fast recovery
fecFactory , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ),
flexfec . NumFECPackets ( 1 ),
)
i . Add ( fecFactory )
// Add NACK as backup
generatorFactory , _ := nack . NewGeneratorInterceptor ()
i . Add ( generatorFactory )
responderFactory , _ := nack . NewResponderInterceptor ()
i . Add ( responderFactory )
// Result: FEC recovers most losses instantly,
// NACK handles remaining losses via retransmission
With Adaptive Bitrate
import (
" github.com/pion/interceptor/pkg/flexfec "
" github.com/pion/interceptor/pkg/gcc "
)
// Monitor packet loss
bwe , _ := gcc . NewSendSideBWE ()
bwe . OnTargetBitrateChange ( func ( bitrate int ) {
stats := bwe . GetStats ()
loss := stats [ "averageLoss" ].( float64 )
// Adjust FEC based on loss
if loss > 0.10 {
// Increase protection in high loss
log . Println ( "High loss detected, consider more FEC" )
} else if loss < 0.02 {
// Reduce overhead in good conditions
log . Println ( "Low loss, FEC overhead could be reduced" )
}
})
CPU Usage
Encoding : ~2-5% CPU per stream (depends on packet size)
Decoding : ~1-3% CPU per stream
Overhead : Increases with packet rate
Bandwidth Overhead
// Calculate bandwidth overhead
func bandwidthOverhead ( mediaRate float64 , numMedia , numFEC uint32 ) float64 {
overhead := float64 ( numFEC ) / float64 ( numMedia )
return mediaRate * overhead
}
// Example: 2 Mbps stream with 5+2 configuration
overheadBW := bandwidthOverhead ( 2_000_000 , 5 , 2 ) // 800 Kbps additional
totalBW := 2_000_000 + overheadBW // 2.8 Mbps total
Latency
Encoding delay : Minimal (< 1ms)
Block delay : Time to collect media packets
5 packets at 30fps: ~167ms
5 packets at 60fps: ~83ms
FEC adds less latency than NACK retransmission (no round-trip time), making it ideal for real-time applications.
Choosing Configuration
Based on Network Conditions
func chooseFECConfig ( estimatedLoss float64 ) ( uint32 , uint32 ) {
switch {
case estimatedLoss < 0.05 :
return 10 , 1 // Light protection
case estimatedLoss < 0.10 :
return 5 , 2 // Medium protection
default :
return 3 , 2 // Heavy protection
}
}
mediaPackets , fecPackets := chooseFECConfig ( 0.08 )
fecFactory , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( mediaPackets ),
flexfec . NumFECPackets ( fecPackets ),
)
Based on Content Type
// Voice (low bitrate, bursty loss)
voiceFEC , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 10 ),
flexfec . NumFECPackets ( 2 ),
)
// Video (high bitrate, continuous)
videoFEC , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 5 ),
flexfec . NumFECPackets ( 2 ),
)
// Screen sharing (bursty, loss sensitive)
screenFEC , _ := flexfec . NewFecInterceptor (
flexfec . NumMediaPackets ( 3 ),
flexfec . NumFECPackets ( 2 ),
)
Best Practices
Start Conservative : Begin with 5+2 configuration
Monitor Loss : Adjust based on actual packet loss rates
Consider Latency : Smaller blocks reduce latency but increase overhead
Bandwidth Budget : Account for FEC in bitrate calculations
Combine Strategies : Use with NACK for comprehensive protection
FlexFEC works best for packet loss between 5-20%. Below 5%, the overhead may not be justified. Above 20%, consider network improvements.
Limitations
Can only recover up to K lost packets per block
Requires additional bandwidth (overhead)
Not effective for very high loss rates (> 30%)
Introduces slight latency (block collection time)
Troubleshooting
FEC packets not generated
Check:
Stream has FEC SSRC configured
Stream has FEC payload type configured
Media packets are flowing
Enough packets collected for a block
Reduce FEC overhead:
Increase NumMediaPackets
Decrease NumFECPackets
Use FEC only when needed
Still experiencing packet loss
Possible causes:
Loss exceeds FEC protection level
Burst losses larger than recovery capability
FEC packets also getting lost
Solutions:
Increase NumFECPackets
Add NACK as backup
Reduce media bitrate
NACK - Complementary retransmission-based recovery
Jitter Buffer - Smooth packet arrival
Stats - Monitor loss and recovery rates