Community support

· 5 min read

ffmpeg trim video

How to cut a clip out of a video with FFmpeg — frame-accurate vs fast and lossless, where to put -ss, and why -c copy sometimes lands seconds off.

ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -ss 00:00:03 -to 00:00:08 output.mp4

That takes a 5-second segment starting at 0:03 and ending at 0:08. It re-encodes with libx264/AAC defaults, the result is frame-accurate, and it works on any input FFmpeg can read. It’s the canonical trim recipe from our FFmpeg cheatsheet.

If you need it faster — orders of magnitude faster, since stream copy skips the encoder — or if you don’t want to re-encode at all, there’s a trade-off.

What -ss, -to, and -t actually mean

-ss is the seek time. -to is the end time. -t is the duration, an alternative to -to.

-ss placement matters more than any other detail in this workflow:

  • -ss before -i — input seeking. FFmpeg jumps to the nearest keyframe before your timestamp. Very fast on long files.
  • -ss after -i — output seeking. FFmpeg decodes the whole input from frame 0 and discards everything before your timestamp. Slow on long files, exact on short ones.

Since FFmpeg 2.1, input seeking is also frame-accurate when transcoding. The FFmpeg Seeking wiki calls this out:

As of FFmpeg 2.1, when transcoding with ffmpeg (i.e. not stream copying): -ss is also ‘frame-accurate’ even as input option. Previous behavior (seek only to nearest preceding keyframe, despite inaccuracy) can be restored with -noaccurate_seek.

Unless you’re using -c copy, where -ss goes barely matters. The combined input-and-output -ss pattern older guides recommend is, in the wiki’s words, “mostly meaningless” today.

The keyframe-only behavior only survives under -c copy.

The fast, lossless cut

ffmpeg -ss 00:00:03 -to 00:00:08 -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c copy output.mp4

-c copy skips the encoder entirely. Packets are remuxed straight into the new container with no quality loss, and the runtime is dominated by I/O rather than CPU.

The catch: copy can only cut on keyframes. If you ask for 00:00:03 and the previous keyframe is at 00:00:00, FFmpeg has to include everything from 00:00:00 forward.

Run that command against the sample file above — h264, 24 fps, default keyint=250, so a keyframe every ~10 seconds. The 3 → 8 cut produces a 5.17s output (167 ms of slop). ffprobe -show_entries packet=pts_time,flags shows what’s inside:

-3.000000,KD_    ← keyframe, flagged "Discard"
-2.833333,_D_    ← 71 packets at negative timestamps, all flagged Discard
-2.875000,_D_
...
-0.041667,_D_
 0.000000,___    ← playable content starts here
 0.041667,___

FFmpeg keeps the keyframe at -3.0s because every frame between -3.0s and 0.0s depends on it for decode, and it marks the in-between frames as discard. A well-behaved player honors the flag and starts at PTS 0. A naive player decodes the lot, and you see what users keep reporting on the VideoHelp forums: black frames, garbled output, or the clip “starting at the wrong second.” VideoHelp regular pcspeak puts the bound at: “ffmpeg cuts at the nearest keyframe. Each cut could differ from your requirements by as much as 4 seconds.”

This isn’t a bug — it’s the price of -c copy. Three ways out if you need accuracy: re-encode (the canonical first command), round your timestamps to known keyframe positions, or use the trim filter (below).

The hybrid: fast and accurate

For long files where you need both speed and accuracy, place a coarse -ss before -i to jump close to the target via keyframe, then a fine -ss after -i to fine-tune frame-accurately, and let FFmpeg re-encode the result:

ffmpeg -ss 00:05:00 -i https://storage.rendi.dev/sample/big_buck_bunny_720p.mp4 -ss 00:00:02 -to 00:00:07 -c:v libx264 -c:a aac output.mp4

Input-seek lands you near 0:05:00 via the prior keyframe, output-seek trims another 2 seconds off the front, the output is a 5-second clip starting exactly where you asked. This is the pattern Carl Eugen Hoyos — 2,166 commits to FFmpeg — recommended on the user mailing list when you’re cutting a few seconds out of a multi-hour file and don’t want to wait for output-seek to decode from frame 0.

-to versus -t

-to is an end position, -t is a duration. With -ss after -i, they’re not interchangeable — -t measures from the seek point, -to measures absolute source time. Full mechanics in ffmpeg -t vs -to.

Multiple cuts in one pass: the trim filter

When you need to splice several segments out of one input — keep 0:03–0:08, drop 0:08–0:21, keep 0:21–0:25 — -ss and -to can’t help. Each invocation cuts one window. You use the trim filter inside -filter_complex:

ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -filter_complex \
  "[0:v]trim=start=3:end=8,setpts=PTS-STARTPTS[v1]; \
   [0:a]atrim=start=3:end=8,asetpts=PTS-STARTPTS[a1]; \
   [0:v]trim=start=11:end=15,setpts=PTS-STARTPTS[v2]; \
   [0:a]atrim=start=11:end=15,asetpts=PTS-STARTPTS[a2]; \
   [v1][a1][v2][a2]concat=n=2:v=1:a=1[v][a]" \
  -map "[v]" -map "[a]" output.mp4

Three caveats:

  1. trim is video, atrim is audio. Reusing trim on an audio stream throws a media-type-mismatch error — a common stumble on first use.
  2. You always need setpts=PTS-STARTPTS (and asetpts for audio). The trim filter gates frames through without rewriting timestamps. Without the reset, downstream concat sees gaps and the output freezes.
  3. setpts/asetpts must come last in the chain. Anything after them re-introduces the gap.

The filter is by Anton Khirnov — 5,751 commits to FFmpeg — added in 2013 for frame-accurate selection inside a filtergraph.

Quick decision matrix

You want…Use
Frame-accurate, any input, simplest command-ss and -to after -i, re-encode (default)
Fastest cut, no quality loss, OK with keyframe alignment-ss and -to before -i, plus -c copy
Fast on a long file and accurateHybrid: coarse -ss before -i, fine -ss after -i, re-encode
Multiple segments stitched in one passtrim + atrim + setpts/asetpts + concat

The rest of FFmpeg’s trim and seek surface is commentary on those four cases — see the FFmpeg Seeking wiki for the full reference.

For more recipes — crop, concat, overlays, audio mixing — see the FFmpeg cheatsheet.

Related Posts

View All Posts →