FFmpeg Tee Muxer: Stream to RTMP and Save Locally
This guide explains how to use the FFmpeg tee muxer to
split a single media stream into multiple outputs simultaneously. By
leveraging this method, you can broadcast a live stream to an RTMP
destination (such as YouTube, Twitch, or a custom media server) while
archiving the identical raw or encoded video to a local disk file in one
single, resource-efficient FFmpeg process.
The Basic Command
To stream to RTMP and save to a local MP4 file without re-encoding twice, use the following syntax:
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k \
-c:a aac -b:a 128k -f tee -map 0:v -map 0:a \
"[f=flv]rtmp://your-rtmp-server/live/streamkey|[f=mp4]local_backup.mp4"If your source input is already encoded in an RTMP-compatible format (H.264 video and AAC audio), you can pass through the streams without re-encoding to save CPU power:
ffmpeg -re -i input.mp4 -c copy -f tee -map 0:v -map 0:a \
"[f=flv]rtmp://your-rtmp-server/live/streamkey|[f=mp4]local_backup.mp4"Command Breakdown
-re: Reads the input at its native frame rate. This is required when streaming from a pre-recorded file to simulate a real-time live broadcast. If using a capture device (like a webcam or capture card), omit this flag.-c:vand-c:a: Specifies the video and audio codecs. Encoding happens once before passing the data to the muxer, ensuring duplicate encoding work is avoided.-f tee: Activates theteemuxer, which allows writing identical packets to multiple outputs.-map 0:v -map 0:a: Explicitly maps all video and audio streams to the outputs. Theteemuxer requires explicit stream mapping to ensure tracks are properly routed to each sub-destination."[f=flv]rtmp://...|[f=mp4]output.mp4": The core of theteemuxer. Individual outputs are separated by a pipe (|) character, and parameters for each output are wrapped in square brackets:[f=flv]: Forces the FLV container format required by RTMP ingest servers.[f=mp4]: Defines the container format for the local file output.
Preventing Stream
Drops with onfail=ignore
By default, if one output in the tee muxer fails (such
as a temporary network disconnection to your RTMP server), the entire
FFmpeg process terminates, killing your local recording. To keep the
local recording running even if the RTMP connection drops, add the
onfail=ignore flag to the RTMP destination:
ffmpeg -re -i input.mp4 -c copy -f tee -map 0:v -map 0:a \
"[f=flv:onfail=ignore]rtmp://your-rtmp-server/live/streamkey|[f=mp4]local_backup.mp4"Handling MP4 File Finalization
Standard MP4 files store their metadata index (the moov
atom) at the end of the file when FFmpeg safely closes. If an unexpected
power outage or crash occurs, the MP4 recording may become corrupted.
You can mitigate this by passing the movflags=faststart or
movflags=frag_keyframe option directly to the MP4 output
inside the tee string:
ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac -f tee -map 0:v -map 0:a \
"[f=flv:onfail=ignore]rtmp://your-rtmp-server/live/streamkey|[f=mp4:movflags=frag_keyframe+empty_moov]local_backup.mp4"Alternatively, you can save the local file using the Matroska
container (.mkv), which is inherently resilient to crashes
and does not require complex finalization flags:
ffmpeg -re -i input.mp4 -c copy -f tee -map 0:v -map 0:a \
"[f=flv:onfail=ignore]rtmp://your-rtmp-server/live/streamkey|[f=matroska]local_backup.mkv"