Skip to main content
The Pion Interceptor library provides a pluggable architecture for processing RTP (Real-time Transport Protocol) and RTCP (RTP Control Protocol) packets in WebRTC applications. This design allows you to add custom functionality to peer connections by intercepting and modifying packets as they flow through your application.

Core design principles

The interceptor architecture is built around several key principles:

Composability

Interceptors can be chained together to build complex processing pipelines from simple, focused components.

Bidirectional processing

Support for both incoming and outgoing packet streams, with separate interfaces for RTP and RTCP protocols.

Stream awareness

Each interceptor receives context about the media stream it’s processing through the StreamInfo type.

Lifecycle management

Explicit bind and unbind hooks allow interceptors to manage resources tied to stream lifecycles.

Packet flow

Packets flow through interceptors in a pipeline pattern:
┌─────────────────────────────────────────────────────────┐
│                    Application Layer                     │
└──────────────────────┬──────────────────┬───────────────┘
                       │                  │
                  Outgoing            Incoming
                       │                  │
                       ▼                  ▼
            ┌──────────────────┐  ┌──────────────────┐
            │  Interceptor 1   │  │  Interceptor 1   │
            │  BindLocalStream │  │ BindRemoteStream │
            │  BindRTCPWriter  │  │  BindRTCPReader  │
            └────────┬─────────┘  └────────┬─────────┘
                     │                     │
                     ▼                     ▼
            ┌──────────────────┐  ┌──────────────────┐
            │  Interceptor 2   │  │  Interceptor 2   │
            └────────┬─────────┘  └────────┬─────────┘
                     │                     │
                     ▼                     ▼
            ┌──────────────────┐  ┌──────────────────┐
            │  Interceptor N   │  │  Interceptor N   │
            └────────┬─────────┘  └────────┬─────────┘
                     │                     │
                     ▼                     ▼
            ┌─────────────────────────────────────────┐
            │          Network Transport              │
            └─────────────────────────────────────────┘

Component overview

Interceptor interface

The central Interceptor interface defines methods for binding to different packet flows. See Interceptor interface for details.

Chain

The Chain type allows multiple interceptors to be composed into a single interceptor. It executes all child interceptors in order. See Chaining interceptors for details.

Registry

The Registry manages interceptor factories and builds complete interceptor chains. See Registry for details.

Supporting types

  • StreamInfo: Provides context about the media stream being processed
  • Attributes: A generic key-value store for passing metadata between interceptors
  • Reader/Writer interfaces: Abstract the packet I/O operations
See Attributes and StreamInfo for details.

Reader and Writer interfaces

The library defines separate reader and writer interfaces for RTP and RTCP packets:
// RTPWriter is used by Interceptor.BindLocalStream.
type RTPWriter interface {
    // Write a rtp packet
    Write(header *rtp.Header, payload []byte, attributes Attributes) (int, error)
}

// RTPReader is used by Interceptor.BindRemoteStream.
type RTPReader interface {
    // Read a rtp packet
    Read([]byte, Attributes) (int, Attributes, error)
}
RTP packets are processed individually, while RTCP packets are processed in batches. This reflects the typical usage patterns of these protocols.

Functional adapters

For convenience, the library provides functional adapters that implement these interfaces:
type RTPWriterFunc func(header *rtp.Header, payload []byte, attributes Attributes) (int, error)
type RTPReaderFunc func([]byte, Attributes) (int, Attributes, error)
type RTCPWriterFunc func(pkts []rtcp.Packet, attributes Attributes) (int, error)
type RTCPReaderFunc func([]byte, Attributes) (int, Attributes, error)
These allow you to use functions directly where reader/writer interfaces are expected.

Factory pattern

Interceptors are created through factories that implement the Factory interface:
// Factory provides an interface for constructing interceptors.
type Factory interface {
    NewInterceptor(id string) (Interceptor, error)
}
This pattern enables:
  • Lazy instantiation of interceptors
  • Per-connection interceptor instances
  • Configuration validation at creation time
  • Error handling during initialization
The id parameter typically corresponds to a PeerConnection identifier, allowing interceptors to maintain per-connection state.

Use cases

The interceptor architecture supports a wide range of use cases:
  • Statistics collection: Monitor packet rates, bandwidth usage, and packet loss
  • Quality of service: Implement congestion control and bandwidth estimation
  • Packet modification: Add or modify RTP header extensions
  • Protocol extensions: Implement custom RTCP feedback mechanisms
  • Recording: Capture media streams for later playback
  • Simulcast: Manage multiple quality layers for adaptive streaming
  • Encryption: Add end-to-end encryption layers
  • Testing: Inject packet loss or delays for testing purposes

Next steps

Interceptor interface

Learn about the core Interceptor interface and lifecycle

Chaining interceptors

Compose multiple interceptors into processing pipelines

Registry

Manage interceptor factories with the Registry

Attributes and StreamInfo

Work with stream metadata and attributes

Build docs developers (and LLMs) love