src/server/internal/direct/webrtcapi.go
2,365 bytes · 75 lines · capsule://quake0day/[email protected]
raw on github
package direct
import (
"github.com/pion/interceptor"
"github.com/pion/interceptor/pkg/cc"
"github.com/pion/interceptor/pkg/gcc"
"github.com/pion/webrtc/v4"
)
// WebRTCAPIConfig configures the shared webrtc.API with interceptors.
type WebRTCAPIConfig struct {
InitialBitrate int // bps, default 1_000_000 (1 Mbps)
MinBitrate int // bps, default 100_000 (100 kbps)
MaxBitrate int // bps, default 10_000_000 (10 Mbps)
}
// NewWebRTCAPI creates a webrtc.API with production interceptors:
// NACK generator/responder, RTCP Reports, TWCC, GCC Pacer.
// Returns (api, estimatorChan) — estimatorChan delivers one BandwidthEstimator per PeerConnection.
func NewWebRTCAPI(cfg WebRTCAPIConfig) (*webrtc.API, <-chan cc.BandwidthEstimator, error) {
if cfg.InitialBitrate <= 0 {
cfg.InitialBitrate = 1_000_000
}
if cfg.MinBitrate <= 0 {
cfg.MinBitrate = 100_000
}
if cfg.MaxBitrate <= 0 {
cfg.MaxBitrate = 10_000_000
}
m := &webrtc.MediaEngine{}
if err := m.RegisterDefaultCodecs(); err != nil {
return nil, nil, err
}
i := &interceptor.Registry{}
// 1) GCC + NoOp pacer (must be before RegisterDefaultInterceptors).
// Real-time pacing lives in DirectPeer.publishAVSegment; leaky-bucket pacing
// plus GCC dropping to MinBitrate during segment idle mis-queues RTP.
congestionController, err := cc.NewInterceptor(func() (cc.BandwidthEstimator, error) {
return gcc.NewSendSideBWE(
gcc.SendSideBWEInitialBitrate(cfg.InitialBitrate),
gcc.SendSideBWEMinBitrate(cfg.MinBitrate),
gcc.SendSideBWEMaxBitrate(cfg.MaxBitrate),
gcc.SendSideBWEPacer(gcc.NewNoOpPacer()),
)
})
if err != nil {
return nil, nil, err
}
estimatorChan := make(chan cc.BandwidthEstimator, 1)
congestionController.OnNewPeerConnection(func(id string, estimator cc.BandwidthEstimator) {
estimatorChan <- estimator
})
i.Add(congestionController)
// 2) TWCC header extension (required by GCC, must be before RegisterDefaultInterceptors)
if err := webrtc.ConfigureTWCCHeaderExtensionSender(m, i); err != nil {
return nil, nil, err
}
// 3) Default interceptors: NACK generator/responder, RTCP Reports, Stats, TWCC sender
if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
return nil, nil, err
}
api := webrtc.NewAPI(
webrtc.WithMediaEngine(m),
webrtc.WithInterceptorRegistry(i),
)
return api, estimatorChan, nil
}