FFmpeg trims video with three options: -ss (where to start), -to (where to end) and -t (how long). You can set the cut points to the millisecond. Copying the streams (-c copy) is fast, but the start snaps to a keyframe. Re-encoding is slower, but the cut lands on the exact frame.

Quick Reference

Option Position Meaning Example
-ss position Before or after -i Start position (time from the start of the file) -ss 00:01:30
-to position Before or after -i End position (before -i: time in the source file; after -i: time in the output, so with an input-side -ss it acts as a length from the -ss point) -to 00:03:00
-t duration Before or after -i How long to extract -t 90
-c copy Output option Stream copy — no re-encoding -c copy
-avoid_negative_ts 1 Output option Avoid negative timestamps (recommended with -c copy) -avoid_negative_ts 1

Use either -to or -t, not both. If you give both, -t wins.

Time Formats

FFmpeg accepts two time formats, and you can use either.

Format Example Meaning
HH:MM:SS 00:01:30 1 minute 30 seconds
HH:MM:SS.mmm 00:01:30.500 1 minute 30 seconds, 500 ms
Decimal seconds 90 or 90.5 90 seconds (90.5 seconds)

If your editor shows only a frame number or a plain count of seconds, the timecode converter turns it into HH:MM:SS.mmm and back. It also handles drop-frame timecode.

Command Examples

1. Basic: Fast Stream-Copy Trim (Speed Priority)

Nothing is re-encoded, so it finishes in seconds. The start point snaps to the keyframe at or before the time you set (see below).

ffmpeg -ss 00:01:00 -to 00:03:00 -i input.mp4 -c copy output.mp4
  • -ss 00:01:00 — start at 1 minute (a fast seek, because it comes before -i)
  • -to 00:03:00 — end at 3 minutes, which gives a 2-minute clip. Before -i it is a time in the source file. After -i it would count from the -ss point instead and give 1:00–4:00 (3 minutes)
  • -c copy — copy the audio and video without re-encoding
# Extract 60 seconds starting at 1m30s, using duration instead of end timestamp
ffmpeg -ss 00:01:30 -i input.mp4 -t 60 -c copy output.mp4

2. Frame-Accurate Trim with Re-Encoding (Accuracy Priority)

With -ss before -i, FFmpeg jumps quickly to a point near the start, then re-encodes from there. This gives the best balance of speed and accuracy.

ffmpeg -ss 00:00:30 -to 00:01:30 -i input.mp4 -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4
  • -crf 23 — H.264 quality (lower = better quality; recommended: 18–28)
  • -preset fast — balances encoding speed and compression
# Using duration instead of -to
ffmpeg -ss 00:02:00 -i input.mp4 -t 45 -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4

3. Multiple Segments in One Pass

This cuts several clips from the same source file with one FFmpeg command. The file is opened only once.

ffmpeg -i input.mp4 \
  -ss 00:00:10 -to 00:01:00 -c copy clip1.mp4 \
  -ss 00:02:30 -to 00:03:15 -c copy clip2.mp4 \
  -ss 00:05:00 -to 00:06:30 -c copy clip3.mp4

Here -ss comes after -i and the streams are copied (-c copy), so each clip’s video starts at the first keyframe after the requested time. The audio starts on time. To cut exactly, re-encode with -c:v libx264 -crf 23 -c:a aac instead of -c copy.

4. Keyframe-Aligned Trim (Exact Start with Stream Copy)

Find the keyframe times with ffprobe, then set -ss to one of them. The video then begins exactly at that time. With any other start time, a stream copy also keeps the part from the keyframe before it and relies on the MP4 edit list to hide that part (see Problem 5).

# List I-frame (keyframe) timestamps
ffprobe -v quiet -select_streams v -skip_frame nokey \
  -show_entries frame=pts_time,pict_type \
  -of csv=p=0 input.mp4 | grep ",I"

Sample output:

0.000000,I
2.002000,I
4.004000,I

Set -ss to one of these times. With the 2.002 s interval above, 64.064 s (00:01:04.064) is one of them:

ffmpeg -ss 00:01:04.064 -i input.mp4 -t 30 -c copy output.mp4

5. Batch Trimming (Shell Script)

To trim many files at once, use a loop:

#!/bin/bash
# Extract a 60-second preview (starting at 10s) from every .mp4 in the current directory
for f in *.mp4; do
  ffmpeg -ss 10 -i "$f" -t 60 -c copy "preview_${f}" -y
done

Input-Side vs. Output-Side -ss (The Key Distinction)

Where you put -ss, before or after -i, decides the trade-off between speed and accuracy.

ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -c copy output.mp4
#       ↑ before -i
Property Detail
Mechanism Fast-seeks to the keyframe just before the specified time
Speed Very fast — seconds even for large files
Accuracy Rounds to keyframe boundary; may start slightly before specified time
Best for Stream-copy cuts, preview clips, rough trims

Output-Side -ss (Slow but Frame-Accurate)

ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c:v libx264 -crf 23 -c:a aac output.mp4
#                   ↑ after -i
Property Detail
Mechanism Decodes from the file start to the exact target frame
Speed Slow — may take minutes for segments deep in a long file
Accuracy Frame-exact
Best for Cases where output-side placement is unavoidable

With -c copy, nothing is decoded. The video starts at the first keyframe after the given position (the audio starts on time), so the cut is not frame-accurate.

Stream Copy vs. Re-Encode Comparison

Method Command Sketch Speed Accuracy Bitrate (data per second)
Stream copy (input-side -ss) -ss X -to Y -i in -c copy out ★★★ ★★☆ Same as source
Re-encode (input-side -ss) -ss X -to Y -i in -c:v libx264 -crf 23 out ★☆☆ ★★★ Changes (per CRF)
Output-side -ss + stream copy -i in -ss X -to Y -c copy out ★★☆ ★☆☆ (video starts at the keyframe after X) Same as source

In practice, -ss before -i plus -c:v libx264 -crf 23 gives the best balance.

Option Details

-avoid_negative_ts 1

When you stream-copy a section from the middle of a file, some timestamps (PTS) can be negative, and some players then have playback problems. This option prevents that.

ffmpeg -ss 00:00:30 -i input.mp4 -t 60 -c copy -avoid_negative_ts 1 output.mp4

-copyts

Keeps the input’s original timestamps in the output. With -ss before -i, a -to after -i then refers to the source time. In MP4, the skipped part is stored as an empty section at the start, so ordinary trims don’t need this option.

ffmpeg -ss 00:01:00 -i input.mp4 -to 00:01:30 -c copy -copyts clip.mp4

Troubleshooting

Problem 1: Block Artifacts at the Start of the Trimmed Clip

Symptom: The first few seconds of a -c copy trim show green or black blocks.
Cause: With -c copy, the clip always starts at a keyframe, so an ordinary cut does not break the picture. Blocks can appear when the source uses open GOPs: there, the frames right after a keyframe can still refer to pictures before it, and those pictures are not in the clip.
Fix: Re-encode.

ffmpeg -ss 00:01:00 -i input.mp4 -t 60 -c:v libx264 -crf 23 -c:a aac output.mp4

Problem 2: Output Duration Doesn’t Match -to Value

Symptom: -ss 00:01:00 -i input.mp4 -to 00:02:00 was meant to give 1 minute, but the output is 2 minutes long.
Cause: With -ss before -i, the output timestamps start again from 0. A -to after -i is compared with those output timestamps, so it means “2 minutes from the -ss point”.
Fix: Use -t (a duration) for a predictable result, or put -to before -i so it refers to the source time:

ffmpeg -ss 00:01:00 -i input.mp4 -t 60 -c copy output.mp4

Problem 3: Output Has No Audio (or No Video)

Symptom: The output opens, but only audio plays, or only video shows.
Cause: The source may not have that stream, or -an or -vn was added by mistake.
Fix:

# Verify streams
ffprobe -v quiet -show_streams input.mp4

# Explicitly copy both streams
ffmpeg -ss 00:01:00 -i input.mp4 -t 60 -c:v copy -c:a copy output.mp4

Problem 4: Output file is empty, nothing was encoded

Symptom: FFmpeg finishes without an error, but the output file has no video or audio (it is only a few hundred bytes).
Cause: The -ss time is past the end of the video.
Fix:

# Check total duration first
ffprobe -v quiet -show_entries format=duration -of default=noprint_wrappers=1 input.mp4

Problem 5: Audio and Video Out of Sync After Trim

Symptom: In the trimmed clip, the lips don’t match the audio.
Cause: With -c copy, the video can only start on a keyframe, so it starts at the keyframe before your position. MP4 stores an edit list that hides that extra part. If the player doesn’t handle the edit list correctly, the video looks out of step with the audio.
Fix: Re-encode the video too (or cut on a keyframe). Re-encoding only the audio does not change where the video starts.

# Re-encode the video too, so it starts exactly at the cut point
ffmpeg -ss 00:01:00 -i input.mp4 -t 60 -c:v libx264 -crf 23 -c:a aac output.mp4

FAQ

Q1. Can I place both -ss and -to before the input?
A. Yes. -to also works as an input option: ffmpeg -ss 00:01:00 -to 00:03:00 -i input.mp4 -c copy output.mp4 cuts 1:00–3:00 of the source (2 minutes). If you put -to after -i instead, it counts from the -ss point (see Problem 2).

Q2. Can I specify a frame number instead of a timestamp?
A. Not directly, but you can convert: frame ÷ frame_rate = seconds. For example, frame 600 at 30 fps is -ss 20.

Q3. Does stream copy degrade quality?
A. No. -c copy passes the audio and video data through unchanged. The quality is the same as the source. The data per second stays the same, so the file gets smaller in proportion to the part you keep.

Q4. Does this work for H.265 (HEVC) video?
A. Yes. A stream copy (-c copy) keeps whatever codec the source uses. To re-encode to H.265, use -c:v libx265 -crf 28 as the codec option.

Q5. Does this work on Windows Command Prompt?
A. Yes, but cmd.exe does not accept a backslash (\) at the end of a line to continue the command. Write the command on one line, and put quotes around paths that contain spaces:

ffmpeg -ss 00:01:00 -i "C:\videos\input.mp4" -t 60 -c copy "C:\output\clip.mp4"