Trim a video with FFmpeg
Two ways to cut a segment: re-encode for frame-accurate boundaries, or stream copy for speed when your cut points sit on keyframes. Both were run on a 12 s test file and the results are below.
Verified with FFmpeg 9.0.1 on 26 August 2026. Search intent: ffmpeg trim video.
ffmpeg -ss 2.5 -to 7 -i input.mp4 -c:v libx264 -preset veryfast -crf 18 -c:a aac -b:a 128k trimmed.mp4Seeks to 2.5 s, stops at 7 s and re-encodes video and audio so the cut lands exactly where you asked. The output is 4.50 s long, 135 frames at 30 fps, with the audio starting on the same sample.
Flags, explained
- -ss 2.5
- Start position in seconds (00:00:02.5 also works). Placed before -i it seeks in the input, which is fast because nothing before the seek point is decoded.
- -to 7
- Absolute end position. Use -t for a duration instead.
- -c:v libx264 -crf 18
- Re-encode the video with x264 at constant quality 18, visually close to the source. Required for a frame-accurate cut.
- -preset veryfast
- Trade some compression for encode speed. Fine for cuts; use medium or slow when file size matters.
- -c:a aac -b:a 128k
- Re-encode the audio so it starts exactly at the cut. With -c:a copy the audio packets from the previous keyframe are kept and hidden behind an edit list.
- -c copy
- Copy every stream without decoding. Instant, lossless, but the cut snaps to keyframes.
Variants
Fast cut without re-encoding (keyframe-bound)
ffmpeg -ss 2.5 -to 7 -i input.mp4 -c copy trimmed.mp4Nothing is decoded, so it finished in 0.04 s on the test file. The catch: with -c copy the video can only start at a keyframe, so FFmpeg keeps everything from the last keyframe before 2.5 s. On our file (one keyframe every 8.3 s) the "4.5 s" clip contained 212 video frames, 7 s of video, with a frozen picture until 2.5 s in players that ignore edit lists. Use it when the source has frequent keyframes or when a second of slack does not matter.
Give a duration instead of an end time
ffmpeg -ss 2.5 -t 4.5 -i input.mp4 -c:v libx264 -preset veryfast -crf 18 -c:a aac -b:a 128k trimmed.mp4-t is a duration, -to is an absolute end time. Both produced the same 4.5 s file here. Pick whichever matches the numbers you already have.
Keep everything from a timestamp to the end
ffmpeg -ss 8 -i input.mp4 -c:v libx264 -preset veryfast -crf 18 -c:a aac -b:a 128k tail.mp4No -to or -t means "until the end". The 12 s test file became a 4.0 s clip of 120 frames. Do not use -c copy for this on a file with sparse keyframes: the same cut with -c copy returned all 360 frames and a file the same size as the input.
Slow but exact seek, with -ss after -i
ffmpeg -i input.mp4 -ss 2.5 -to 7 -c:v libx264 -preset veryfast -crf 18 -c:a aac -b:a 128k trimmed.mp4With -ss after the input, FFmpeg decodes and discards everything before 2.5 s instead of jumping there. Same 135-frame result, slower on long files. Only needed when a filter depends on absolute timestamps from the start of the file.
Pitfalls we hit
- Stream copy starts at the previous keyframe, not at -ss. On the test file, -ss 2.5 -to 7 -c copy kept 212 frames (7 s of video) for a reported duration of 4.57 s.
- Stream copy from a late timestamp can return the whole file: -ss 8 -c copy on a file whose only keyframes sit at 0 s and 8.33 s produced all 360 frames and 4.9 MB, the same size as the input.
- Putting -ss after -i decodes everything before the cut. Correct, but slow on long recordings.
- Copying audio (-c:a copy) while re-encoding video leaves extra audio packets in the file behind an edit list (330 AAC frames for a 4.5 s clip here). Most players honour the edit list; some older ones do not.
How we verified it
Run with FFmpeg 9.0.1 on 26 August 2026 against a 12 s, 1280x720, 30 fps H.264/AAC file with a keyframe every 250 frames. Primary command: 135 video frames, 212 AAC frames, duration 4.500 s, 2.3 MB. Stream copy: 212 video frames, reported duration 4.567 s, 2.9 MB, 0.04 s wall time. -ss 8 with -c copy: 360 frames, 4,896,094 bytes, identical to the input size. -ss 8 re-encoded: 120 frames, 4.000 s.
The same edit as a typed operation
trim_video takes start and end in seconds, validates them against the probed duration and returns an MP4 with exact boundaries. It uses stream copy when the cut lands on keyframes and re-encodes otherwise, so the caller never chooses.
{
"inputs": [{ "id": "main", "url": "https://example.com/video.mp4" }],
"options": { "start": 2.5, "end": 17 }
}FAQ
Why is my trimmed video longer than the times I gave?
You used -c copy. Without re-encoding, FFmpeg can only start the video at a keyframe, so it keeps the frames between the previous keyframe and your start time. Re-encode the video (-c:v libx264) or accept the slack.
Does trimming with FFmpeg lose quality?
With -c copy, no: the compressed frames are copied as they are. With a re-encode, a small amount, kept negligible with -crf 18 or lower. Audio is re-encoded to AAC at 128 kbps in the primary command; raise -b:a if the source is music.
Should -ss go before or after -i?
Before -i in almost every case: it seeks the input directly and is fast. After -i, FFmpeg decodes from the start and drops frames until the timestamp, which is only useful when a later filter needs the original timeline.
Can I cut several segments from one file in one command?
Yes, by listing several outputs with their own -ss and -t after the input, or with the trim and atrim filters. Each output is encoded separately, so it costs the same as running the command several times.
Related commands
- ffmpeg extract audioExtract audio from a video with FFmpegRead
- ffmpeg video to gifConvert a video to GIF with FFmpegRead
- ffmpeg compress videoCompress a video with FFmpegRead