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.mp4

This guarantees an accurate, clean, and lossless cut directly on native keyframe boundaries.