How to Split Streams with the FFmpeg Tee Protocol
This guide explains how to use FFmpeg's tee muxer to
duplicate and distribute a single audio/video stream across multiple
network destinations simultaneously. By routing your output through
tee, you can stream to multiple endpoints—such as
concurrent RTMP live platforms or UDP network targets—while encoding the
source media only once, drastically reducing CPU overhead and memory
usage.
The Basic Syntax of the
tee Muxer
While commonly discussed as a protocol, FFmpeg implements stream
splitting via the tee pseudo-muxer (-f tee).
It takes multiple outputs separated by the pipe (|)
character within quotes. Each output can specify its own format and
options inside brackets [...].
The fundamental command structure is:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f tee -map 0:v -map 0:a "[f=flv]rtmp://server1/live/stream1|[f=flv]rtmp://server2/live/stream2"Splitting to Multiple RTMP Destinations
A common network use case is broadcasting a single live stream to two different ingest servers (such as YouTube and Twitch). Instead of running two separate FFmpeg instances or re-encoding the stream, encode once and write to both targets:
ffmpeg -re -i input.mp4 \
-c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k \
-c:a aac -b:a 160k \
-flags +global_header \
-f tee -map 0:v -map 0:a \
"[f=flv]rtmp://a.rtmp.youtube.com/live2/YOUR_YT_KEY|[f=flv]rtmp://live.twitch.tv/app/YOUR_TWITCH_KEY"The -flags +global_header flag is recommended when
multiplexing to container formats like FLV to ensure headers are
properly transmitted to all RTMP endpoints.
Splitting to Heterogeneous Network Protocols (RTMP + UDP/RTP)
You can output to completely different container formats and network transport protocols from the same pipeline:
ffmpeg -re -i input.mp4 \
-c:v libx264 -c:a aac \
-f tee -map 0:v -map 0:a \
"[f=flv]rtmp://live.example.com/app/stream|[f=mpegts]udp://239.255.0.1:1234?pkt_size=1316"In this example, FFmpeg sends one stream as FLV over RTMP and simultaneously packages the identical bitstream as an MPEG-TS container over UDP multicast.
Preventing Stream
Failures with onfail=ignore
By default, if any target in a tee output encounters a
network error (such as a disconnected socket or server timeout), the
entire FFmpeg process terminates. To keep streaming to the remaining
healthy endpoints if one fails, apply onfail=ignore to each
output:
ffmpeg -re -i input.mp4 \
-c:v libx264 -c:a aac \
-f tee -map 0:v -map 0:a \
"[f=flv:onfail=ignore]rtmp://primary.live.com/stream|[f=flv:onfail=ignore]rtmp://backup.live.com/stream"Independent Stream Mapping
The tee muxer allows sending different stream tracks to
different network endpoints. For example, if you want one output to
receive both video and audio, but a secondary network monitor to receive
only the video stream:
ffmpeg -re -i input.mp4 \
-c:v libx264 -c:a aac \
-f tee \
"[select=\'v,a\':f=flv]rtmp://live.example.com/stream|[select=\'v\':f=mpegts]udp://192.168.1.50:5000"Key Considerations
- Bandwidth Requirements: The
teemuxer duplicates data at the application layer. If you are sending two 5 Mbps streams, your outbound network interface must sustain at least 10 Mbps of upload bandwidth. - Escaping Special Characters: If your target URLs
contain special characters or colons inside parameters, wrap the URL
components in single quotes or escape characters with backslashes
(
\) according to your shell environment.