Multi-output encoding with FFmpeg: tee muxer, split filter, and the right pattern
Encode one input into multiple outputs in a single FFmpeg invocation. Split filter, tee muxer, and the throughput math that decides when this beats per-output encoding.
When to use this
You use multi-output encoding when you want one FFmpeg run to produce multiple outputs from the same input — typically an ABR ladder, simultaneous HLS + DASH packaging, or a single live encode fanned out to multiple destinations. The throughput advantage: only one decode pass and one filter pass for shared transformations. The trade-off: one output's failure can block the others, and per-output retry semantics get complicated. For production at scale, individual per-output encoding is usually the right pattern; multi-output is the right call for tightly-coupled outputs (an ABR ladder where all renditions must succeed together) or when decode cost dominates encode cost.
Command variants
ffmpeg -i input.mp4 \
-c:v libx264 -preset medium \
-map 0:v -map 0:a -c:v libx264 -crf 22 -c:a aac -b:a 192k \
output_high.mp4 \
-map 0:v -map 0:a -c:v libx264 -crf 28 -vf scale=854:480 -c:a aac -b:a 96k \
output_low.mp4Two outputs from one input. Each output has its own -map, codec, and filter chain. Decoder runs once.
ffmpeg -i srt://encoder:9999 \
-c:v libx264 -preset veryfast -tune zerolatency \
-c:a aac -b:a 128k \
-f tee "[f=hls:hls_time=2:hls_playlist_type=event]hls/stream.m3u8|[f=flv]rtmp://backup-cdn:1935/live/stream"Single live encode, two simultaneous outputs (HLS file + RTMP push). Common for live streaming with primary + backup destinations.
ffmpeg -i input.mp4 \
-filter_complex "[0:v]split=2[hi][lo];[hi]scale=1920:1080[hi_out];[lo]scale=854:480[lo_out]" \
-map "[hi_out]" -map 0:a -c:v libx264 -crf 22 -c:a aac output_hi.mp4 \
-map "[lo_out]" -map 0:a -c:v libx264 -crf 28 -c:a aac output_lo.mp4Use when outputs share filter chain (scale, crop, etc). Saves duplicate filter passes.
What each parameter does
-mapSelects which input streams go into each output. Multiple -map flags per output spec are common.
-f teeTee muxer for fanning a single encoder output to multiple destinations (files, RTMP, HLS, etc).
split=NFilter that duplicates the input N times into N labeled outputs. Used inside filter_complex.
filter_complexMulti-input/multi-output filter graph. Required for split filter and complex routing.
-tune zerolatencylibx264 tuning for live use cases. Disables b-frames and lookahead. Required for live multi-output.
What this outputs
Multiple output files (file targets) or active streams (live targets). With proper configuration, all outputs are produced from a single decode + encode pass per shared stage. The throughput advantage is most visible when decode is expensive (4K source) or when filters are expensive (complex scaling / color correction).
Pitfalls
- Per-output retry: if one output fails, FFmpeg may abort the entire run depending on the failure. Production-grade ABR ladder generation should use individual per-rendition encoding so failures retry independently.
- Tee muxer error handling is finicky: a network blip on one RTMP destination can stall all destinations. Always pair with separate retry logic.
- Memory usage compounds: each output adds buffer requirements. Multi-output runs can OOM on high-resolution sources where individual runs would succeed.
- Audio re-encoding per-output wastes compute: encode audio once at the highest quality, then stream-copy to each output where compatible.
- Filter graphs with split are powerful but hard to debug. Always test with -filter_complex_threads 1 first to rule out threading issues.
- NVENC multi-output with shared decode works but has known issues with concurrent encoding sessions per GPU. Verify on your specific driver version.
At production scale
At low scale (per-encode count), multi-output is ~10-30% faster than per-output runs because decode + filter passes are shared. At production scale, per-output runs win on operational flexibility (independent retry, per-rendition pool routing, deterministic failure boundaries) — and when decode is fast (H.264 source) the multi-output advantage shrinks. The right pattern: multi-output for tightly-coupled outputs (must-succeed-together ladder), per-output for loosely-coupled outputs (rendition fanout where each can retry independently).
MpegFlow lets you choose multi-output vs per-output per stage in the DAG manifest. The platform handles the operational difference: multi-output stages have unified retry, per-output stages retry per-output. The choice is data-driven, not code-driven.
- FFmpeg
- multi-output
- tee-muxer
- split-filter
- tooling