The fast way to cut a clip out of a video with ffmpeg is to seek to the start, set an end point, and copy the streams without re-encoding:
ffmpeg -ss 00:00:10 -to 00:00:20 -i input.mp4 -c copy out.mp4That pulls seconds 10 to 20 out of input.mp4 into out.mp4 in a fraction of a second, with zero quality loss, because -c copy (stream copy) muxes the existing video and audio packets straight through instead of decoding and re-encoding them. For most "grab this segment" jobs it is the whole answer.
There is one catch worth understanding before you trust the output, and it is the source of nearly every "my cut started in the wrong place" complaint: stream copy can only cut on keyframes. The rest of this page covers that gotcha, the frame-accurate alternative, and what -ss, -to, and -t actually mean.
The fast, lossless cut (-c copy)
Two forms, depending on whether you think in end-time or duration. Use -to for an absolute end timestamp:
# Keep everything from 00:00:10 to 00:00:20 (10 seconds of output)
ffmpeg -ss 00:00:10 -to 00:00:20 -i input.mp4 -c copy out.mp4Or use -t for a duration measured from the start point:
# Start at 00:00:10 and keep 10 seconds
ffmpeg -ss 00:00:10 -t 10 -i input.mp4 -c copy out.mp4-to and -t are not the same flag. -to is an end position (stop at this point); -t is a duration (run for this long). The wrinkle is the seek point. When -ss comes before -i (input seeking, as in every command on this page), ffmpeg resets the timeline to zero at the seek point, so -to is measured from there, not from the start of the original file. That is why -ss 00:00:10 -to 00:00:20 gives you ten seconds, the same clip as -ss 00:00:10 -t 10: with input seeking, -to 20 and -t 10 describe the identical out point. (Put -ss after -i and -to is measured against the original timeline instead, so there -ss 10 -to 20 is also a ten-second clip but for a different reason.) -to and -t are mutually exclusive; if you pass both, -t wins. If a clip ever comes out longer than expected, you have probably reached for -to thinking it meant duration.
This stream-copy command is instant and lossless: nothing is re-compressed, so there is no generation loss and no codec choice to make. It is the right tool for splitting a long screen recording, lopping dead air off the front, or carving a rough segment out of a large file.
The keyframe gotcha (why your cut lands early)
Video is not stored as independent frames. It is stored in groups of pictures (GOPs), each beginning with a keyframe (an I-frame, a complete standalone image), followed by predicted frames that only describe what changed. You cannot start decoding mid-GOP, so a stream copy cannot begin output anywhere except on a keyframe.
That means when you ask for -ss 00:00:10 with -c copy, ffmpeg snaps the start back to the nearest keyframe at or before 10 seconds. If the closest keyframe sits at 00:00:08, your clip begins two seconds early. Nothing is broken and no quality is lost, the cut point is just constrained to where the keyframes are. Keyframe spacing depends on how the source was encoded (often one every 2 to 10 seconds), so the error varies by file.
This is exactly the "result quality varies with -c copy, sometimes it is better without it" confusion you see in old forum threads. It was never random. It is the keyframe constraint. When the start needs to be exact, you re-encode.
The frame-accurate cut (re-encode)
Drop -c copy and ffmpeg decodes the source and re-encodes the output, so it can start on any frame you ask for, not just a keyframe:
# Frame-accurate: exact start, exact length, re-encoded
ffmpeg -ss 00:00:10 -to 00:00:20 -i input.mp4 -c:v libx264 -crf 18 -c:a aac out.mp4This is slower (it does real encoding work) and technically lossy (you are re-compressing), but -crf 18 for libx264 is visually near-transparent, so the quality cost is small. Use it when a couple of stray frames at the head of the clip would be obvious: cutting on a line of dialogue, trimming for social media, or stitching segments that have to line up.
Rule of thumb: reach for -c copy first for speed and zero loss, and only re-encode when the start point has to be precise.
Where -ss goes: before -i vs after -i
You will see -ss written both before and after -i, and the placement used to matter a lot more than it does now.
# -ss before -i: fast input seek (jumps to a keyframe near the time, then reads)
ffmpeg -ss 00:00:10 -i input.mp4 -t 10 -c copy out.mp4
# -ss after -i: ffmpeg reads from the start and discards frames up to -ss
ffmpeg -i input.mp4 -ss 00:00:10 -t 10 -c:v libx264 -crf 18 out.mp4The old story was: -ss before -i is fast but inaccurate, -ss after -i is slow but accurate. That changed with ffmpeg 2.1, which made input seeking frame-accurate when you are re-encoding. So in any modern ffmpeg (you should be on 6.x or 7.x today), -ss before -i is both fast and frame-accurate for a re-encode, and it is the better default: it seeks straight to a keyframe near the target instead of decoding the whole file up to that point.
The placement only really matters in two cases now. With -c copy, accuracy is bounded by keyframes no matter where -ss sits, so put it before -i for the speed. With a re-encode, before--i is faster and just as accurate; the after--i form (decode-and-discard from frame zero) is only worth reaching for if you hit a pathological file where input seeking misbehaves. If you want the legacy keyframe-only input-seek behavior back, -noaccurate_seek restores it.
Timestamp formats
ffmpeg accepts time values in two forms anywhere it wants a time (-ss, -to, -t):
HH:MM:SS.ms, for example00:01:30.500for one minute thirty and a half seconds. Hours and the fractional part are optional, so01:30and90and00:01:30all mean the same point.- Plain seconds, for example
90or90.5. Handy for short clips:-ss 5 -t 3is "start at 5 seconds, keep 3."
Both work in either flag, so mix whichever reads more clearly. Sub-second precision (.ms) matters most on the re-encode path, where the cut can actually land on that exact frame.
Splitting one file into several segments
If the goal is to chop a long file into equal pieces rather than extract one clip, the segment muxer does it in a single pass without re-encoding:
# Split into ~60-second chunks, stream-copied, cut at keyframes
ffmpeg -i input.mp4 -c copy -f segment -segment_time 60 -reset_timestamps 1 part%03d.mp4The same keyframe rule applies: each split lands on the nearest keyframe, so the chunks are approximately 60 seconds, not exactly. For exact-length segments you would re-encode with a forced keyframe interval, but for most "break this up so it uploads" tasks the copy version is what you want.
FAQ
See also
- The ffmpeg command cheat sheet: every common task (convert, crop, trim, compress) with the canonical 2026 command in one reference.
- Crop a video with ffmpeg: the
crop=w:h:x:yfilter, centered crops, and keeping audio untouched with-c:a copy. - Extract audio from a video with ffmpeg: pull the sound to MP3, AAC, or WAV, with the fast
-vn -c:a copyform.
Sources
Authoritative references this article was fact-checked against.
- Seeking, official ffmpeg wikitrac.ffmpeg.org
- ffmpeg documentation, main options (official)ffmpeg.org
- FFmpeg Changelog, accurate input -ss since 2.1 (official)github.com





