Cutting a clip out of a longer video is the most common FFmpeg job, and it has two very different answers. A stream copy (-c copy) is instant and lossless but can only start on a keyframe. A re-encode cuts exactly where you ask but takes time and recompresses the picture. This page measures both on the same file, so you can choose.
All numbers were measured on 2026-11-07 with FFmpeg 9.0.2 (linuxserver/ffmpeg image) on a 10-second 1280×720, 30 fps H.264 test video with AAC audio and a keyframe every 2 seconds (-g 60), which is typical of exported video.
The two commands
# Fast, lossless, starts on a keyframe
ffmpeg -ss 00:00:03 -t 2 -i in.mp4 -c copy out.mp4
# Exact, re-encoded
ffmpeg -ss 00:00:03 -t 2 -i in.mp4 -c:v libx264 -crf 18 -preset medium -c:a aac out.mp4
-ss is the start, -t the length (both accept seconds like 3.5 or HH:MM:SS.ms). -c copy copies the compressed streams; -c:v libx264 -crf 18 re-encodes the video at near-transparent quality.
What we measured
| Cut | Command | Took | Duration | Video frames |
|---|---|---|---|---|
| 3.0 → 5.0 s | -c copy |
0.03 s | 2.07 s | 92 |
| 3.0 → 5.0 s | re-encode | 1.08 s | 2.000 s | 60 |
| 3.5 → 5.5 s (start between keyframes) | -c copy |
0.02 s | 2.17 s | 107 |
The stream copy was about 35 times faster, and for a long film the gap grows with every minute. But a 2-second cut at 30 fps should hold 60 frames, and the copies held 92 and 107. The packets of the second one show why: the first is the keyframe at 2.0 s, 1.5 seconds before the requested start, flagged as "discard". A video frame between keyframes cannot be decoded without the keyframe before it, so FFmpeg copies from there and writes an edit list telling players to skip the first 1.5 seconds.
Players that honour the edit list start on time. Tools that ignore it — some editors, some upload pipelines — show the extra second and a half, or a frozen first frame. The file is also larger than the cut suggests.
Which one to use
- Stream copy when speed matters and a start up to one keyframe interval early is acceptable: splitting a recording into rough parts, removing a long intro, cutting a podcast video at a pause. Check the keyframe spacing first (below); with a keyframe every second, the error is at most a second.
- Re-encode when the cut must be exact — a clip for social media that starts on a word, a GIF, anything you will concatenate with other clips. The cost is time and a second generation of compression;
-crf 18keeps the loss small.
A middle way: re-encode only the clip you need, not the whole file. -ss before -i makes FFmpeg jump close to the start without decoding the minutes before it, so a 2-second cut from a 2-hour file costs roughly the encoding of those 2 seconds, not of the hours before them.
Finding the keyframes
ffprobe -v error -select_streams v:0 -skip_frame nokey \
-show_entries frame=pts_time -of csv=p=0 in.mp4
This prints the time of every keyframe. If your start time is on one of them, -c copy starts exactly there. For our test file it printed 0, 2, 4, 6, 8 — a cut at 3.5 s therefore started at 2.0.
-ss before or after -i
- Before
-i(input seeking): FFmpeg jumps through the file using its index — fast on any length. With re-encoding, current FFmpeg decodes from the keyframe and discards frames up to the exact time, so the cut is still frame-accurate. - After
-i(output seeking): FFmpeg decodes everything from the beginning and throws away frames until the start time. Accurate, but slow on long files.
The FFmpeg wiki's Seeking page confirms both halves of this: input seeking parses the file "by keyframe, which is very fast", and since FFmpeg 2.1 -ss before -i is "frame-accurate" when transcoding, but not when stream copying — exactly what our table shows. The old keyframe-only behaviour can be forced with -noaccurate_seek.
Use -ss before -i in both commands above, and prefer -t (a duration) to -to (an end position): whether -to refers to the input's timeline or the output's depends on where you put it, while -t always means "this long".
Checking a cut
Do not trust the file name or a player's progress bar. ffprobe -v error -show_entries format=duration -of csv=p=0 out.mp4 prints the duration, and adding -count_packets -select_streams v:0 -show_entries stream=nb_read_packets counts the video frames — that is how we found the 107 frames in a cut that should have held 60. If the numbers are off and the cut must be exact, re-encode.
Several clips from one file
ffmpeg -i in.mp4 \
-ss 10 -t 5 -c:v libx264 -crf 18 -c:a aac clip1.mp4 \
-ss 42 -t 8 -c:v libx264 -crf 18 -c:a aac clip2.mp4
Options apply to the output that follows them, so one run writes several clips. For many highlights, a short script that calls FFmpeg once per clip is easier to read and to retry.
Audio-only and vertical cuts
- Audio:
ffmpeg -ss 30 -t 15 -i talk.mp4 -vn -c:a copy clip.m4akeeps only the audio (-vn) without re-encoding — audio frames are short, so copied audio cuts are close to exact. - Vertical for Shorts and Reels: trim and crop in one pass:
-vf "crop=ih*9/16:ih"takes a centred 9:16 slice of a landscape video (re-encoding is required whenever a filter is used).
The official FFmpeg documentation describes -ss, -t and -to under main options, and -c copy under stream copy.
The image every clip needs
Each clip you publish needs a cover: a YouTube thumbnail, a Reel cover, the preview image when the link is shared. We do not cut or edit video — FFmpeg is the right tool for that — but we do make those images. With Shareglint, a thumbnail is a template with the clip's title, a frame or photo and your channel name, rendered at YouTube's 1280×720 with "size": "youtube" (or every social size at once), one request per clip:
curl -X POST "https://shareglint.com/v1/images?wait=true" \
-H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" \
-d '{ "template": "video-thumbnail", "size": "youtube",
"modifications": { "title": "The 2-second cut", "channel": "Trail Notes", "duration": "0:42",
"image": "https://example.com/frame-42s.jpg" } }'
To grab a frame for it, FFmpeg again: ffmpeg -ss 42 -i in.mp4 -frames:v 1 frame-42s.jpg. More on covers in YouTube thumbnails.