gortsplib.Client subscribes to the upstream server, and a gortsplib.Server serves that same stream to local readers. Every inbound RTP packet is forwarded to the server stream in the OnPacketRTPAny callback.
Data flow
Complete example
The proxy is split across three files that form a singlemain package.
How it works
Server initializes
server.initialize() configures a gortsplib.Server listening on :8556. It supports UDP unicast, UDP multicast, and TCP transport. No stream exists yet — DESCRIBE and SETUP return 404 until the client connects upstream.Client connects upstream
client.initialize() starts a goroutine that calls read() in a loop, reconnecting after reconnectPause on any error. Inside read(), a gortsplib.Client connects to the upstream URL, calls Describe to fetch the SDP, and calls SetupAll to set up every media track.Stream becomes available
Once setup succeeds,
setStreamReady(desc) creates a ServerStream using the upstream description.Session directly. The same media descriptions are forwarded to downstream readers, so the SDP is an exact mirror of the upstream.Packets are routed
OnPacketRTPAny fires for every inbound RTP packet on any media. The callback calls stream.WritePacketRTP(medi, pkt), which fans the packet out to all connected downstream readers.Transport selection
By defaultgortsplib.Client negotiates transport automatically (UDP preferred, falls back to TCP). In a proxy you may want to force TCP to avoid NAT/firewall issues with UDP on the upstream leg:
Tunneling
The server supports RTSP-over-HTTP tunneling out of the box — setRTSPOverHTTPAddress on the gortsplib.Server to enable it. RTSP-over-WebSocket tunneling can be enabled with RTSPOverWebSocketAddress.
Back-channel proxy
When the upstream source is an ONVIF camera with a back channel (two-way audio), the proxy must also route RTP packets from downstream readers back to the upstream client. SetRequestBackChannels: true on the client and wire up OnPacketRTPAny on the server’s OnPlay handler to call rc.WritePacketRTP back to the upstream. See the examples/proxy-backchannel directory for the complete implementation.