Cut Video at Exact I-Frames with FFmpeg
Cutting video streams without re-encoding requires splitting precisely at I-frames (keyframes) to prevent corruption, black screens, or playback stutters. This article covers how to accurately cut videos at I-frame boundaries using FFmpeg, detailing how to snap to keyframes automatically using stream copying, how to detect exact I-frame timestamps with FFprobe, and how to split an entire video into segments at every single keyframe.
Understanding I-Frames and Stream Copying
Video compression relies on different frame types:
- I-frames (Intra-coded frames): Complete standalone images (keyframes).
- P-frames and B-frames: Predictive frames that rely on data from previous or subsequent frames.
When using -c copy (stream copying), FFmpeg does not
decode or re-encode the video. Because predictive frames cannot exist
without their referenced I-frame, a lossless cut must start on
an I-frame.
Method 1: Snapping to the Nearest Keyframe Automatically
To make FFmpeg automatically align your cut to the nearest preceding
I-frame, place the -ss parameter before
the input file (-i). This triggers "input seeking," which
seeks directly via keyframes.
ffmpeg -ss 00:01:23.000 -i input.mp4 -to 00:02:45.000 -c copy output.mp4-ss 00:01:23.000: Seeks to the nearest keyframe at or before 1 minute and 23 seconds.-i input.mp4: Specifies the input source.-to 00:02:45.000: Defines the end timestamp.-c copy: Copies the audio and video streams directly without re-encoding.
Note: If you place -ss after
-i, FFmpeg will decode the frames and re-encode up to the
timestamp, which breaks lossless stream copying.
Method 2: Automatically Splitting at Every I-Frame
If you need an automated process that breaks a video file into
segments at every I-frame boundary without manually
specifying timestamps, use the segment muxer with an
impossibly small segment duration:
ffmpeg -i input.mp4 -c copy -f segment -segment_time 0.00001 -reset_timestamps 1 part_%04d.mp4-f segment: Activates the segmenter muxer.-segment_time 0.00001: Instructs FFmpeg to split as frequently as possible. Because stream copying (-c copy) forbids splitting on non-keyframes, FFmpeg falls back to splitting exclusively when it encounters each new I-frame.-reset_timestamps 1: Ensures each resulting clip starts with a timestamp of zero, preventing playback issues.part_%04d.mp4: Outputs numbered files (e.g.,part_0001.mp4,part_0002.mp4).
Method 3: Finding Exact I-Frame Timestamps with FFprobe
To cut at a specific, known I-frame rather than an approximation,
extract the exact keyframe timestamps first using
ffprobe:
ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -of csv input.mp4 | grep ",I"This outputs a list of every I-frame and its exact timestamp in seconds:
frame,12.512500,I
frame,24.024000,I
frame,36.536500,I
Once identified, insert the precise timestamp directly into your cut command:
ffmpeg -ss 12.512500 -to 36.536500 -i input.mp4 -c copy output.mp4This guarantees an accurate, clean, and lossless cut directly on native keyframe boundaries.