FFmpeg Segment Muxer: Split Live Stream at Keyframes
This article explains how to use the FFmpeg segment
muxer to split an incoming live video stream into smaller, sequential
chunks precisely at keyframe boundaries. You will learn the exact
command-line parameters required to ensure seamless playback, avoid
video corruption, and manage how FFmpeg handles keyframes (I-frames)
when slicing a live stream with or without re-encoding.
The Challenge of Splitting Live Streams
When splitting a live video stream into segments (for HTTP Live Streaming (HLS), archiving, or processing), video players require each segment to start with a keyframe (I-frame). If a segment starts with a B-frame or P-frame, the player cannot render the video until it encounters the next keyframe, resulting in frozen frames, green screens, or decoding errors.
FFmpeg’s segment muxer can split streams automatically,
but how it behaves depends entirely on whether you are re-encoding the
video or copying the stream directly.
Method 1: Splitting Without Re-encoding (Stream Copy)
If you want to split the stream without re-encoding (using
-c copy), FFmpeg is highly efficient and uses minimal CPU.
However, because it cannot create new keyframes, FFmpeg can only
split the video at existing keyframes.
If you specify a segment time of 10 seconds, but your stream only has keyframes every 12 seconds, FFmpeg will wait until the 12-second mark to create the split.
Command Example:
ffmpeg -i rtmp://live.example.com/input -c copy \
-f segment \
-segment_time 10 \
-reset_timestamps 1 \
-segment_format mpegts \
output_%03d.tsParameter Breakdown:
-c copy: Copies the video and audio streams without re-encoding, preserving quality and saving CPU.-f segment: Tells FFmpeg to use the segment muxer.-segment_time 10: Sets the target segment duration to 10 seconds. FFmpeg will split at the first keyframe after this duration is reached.-reset_timestamps 1: Resets timestamps at the beginning of each segment so that each output file starts near packet timestamp 0. This is crucial for player compatibility.output_%03d.ts: The output naming pattern. It generates files likeoutput_001.ts,output_002.ts, etc.
Method 2: Splitting with Exact Timing (Re-encoding)
If you require your segments to be split at exact mathematical intervals (e.g., precisely every 5 seconds), you must re-encode the stream. This allows FFmpeg to force keyframes to occur exactly when the segment split is scheduled.
Command Example:
ffmpeg -i rtmp://live.example.com/input \
-c:v libx264 -force_key_frames "expr:gte(t,n_forced*5)" \
-c:a aac \
-f segment \
-segment_time 5 \
-reset_timestamps 1 \
-segment_format mp4 \
output_%03d.mp4Parameter Breakdown for Exact Splits:
-c:v libx264: Re-encodes the video using the H.264 codec.-force_key_frames "expr:gte(t,n_forced*5)": Forces FFmpeg to insert a keyframe precisely every 5 seconds (matching the-segment_time).-segment_time 5: Instructs the segmenter to split every 5 seconds. Because a keyframe is forced at these exact intervals, the segments will be cut cleanly and precisely.
Choosing the Right Segment Format
While MPEG-TS (.ts) is the traditional standard for live
stream segmentation due to its resilience to stream interruptions, you
can also use MP4 (-segment_format mp4) or WebM
(-segment_format webm).
For modern streaming protocols like LL-HLS or DASH, you may want to output fragmented MP4s by adding the appropriate muxer flags:
ffmpeg -i rtmp://live.example.com/input -c copy \
-f segment \
-segment_time 6 \
-segment_format_options movflags=frag_keyframe+empty_moov+default_base_moof \
-reset_timestamps 1 \
output_%03d.mp4