Need to cut just the right segment from a video? FFmpeg’s -ss, -to, and -t options let you trim with millisecond accuracy. Whether you want a lightning-fast stream copy or a frame-perfect re-encode, this guide covers every case. You’ll be trimming like a pro in about 10 minutes.

Tested with: FFmpeg 6.1 (ubuntu-latest / GitHub Actions CI-validated)
Supported OS: Windows / macOS / Linux


What You Will Learn

  1. The meaning and usage of -ss, -to, and -t
  2. Input-side -ss vs. output-side -ss — speed vs. accuracy trade-off
  3. Stream-copy fast trimming and how to fix keyframe artifacts
  4. Frame-accurate trimming with re-encoding
  5. Extracting multiple segments in one command
  6. Finding keyframe positions with ffprobe before cutting
  7. Batch trimming with a shell script
  8. Five common errors and how to fix them
  9. Five frequently asked questions

Quick Reference

OptionPositionMeaningExample
-ss positionBefore or after -iStart position (absolute timestamp)-ss 00:01:30
-to positionBefore output fileEnd position (absolute from file start)-to 00:03:00
-t durationBefore or after -iHow long to extract-t 90
-c copyOutput optionStream copy — no re-encoding-c copy
-avoid_negative_ts 1Output optionAvoid negative timestamps (recommended with -c copy)-avoid_negative_ts 1

-to and -t cannot be used together. If both are specified, -t wins (per the FFmpeg docs).


Time Formats

FFmpeg accepts two time formats interchangeably.

FormatExampleMeaning
HH:MM:SS00:01:301 minute 30 seconds
HH:MM:SS.mmm00:01:30.5001 minute 30 seconds, 500 ms
Decimal seconds90 or 90.590 seconds (90.5 seconds)

Command Examples

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

No re-encoding — completes in seconds. Start point snaps to the nearest keyframe (see details below).

ffmpeg -ss 00:01:00 -i input.mp4 -to 00:03:00 -c copy output.mp4
  • -ss 00:01:00 — start at 1 minute (fast seek before input)
  • -to 00:03:00 — end at 3 minutes (extracts 2-minute clip)
  • -c copy — copy 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)

Input-side -ss fast-seeks to the ballpark, then re-encoding starts from there — the best balance of speed and accuracy.

ffmpeg -ss 00:00:30 -i input.mp4 -to 00:01:30 -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

Extract several clips from the same source file in a single FFmpeg invocation. 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

Note: This uses output-side -ss (slow seek), so extracting segments late in a long video may take longer.

4. Keyframe-Aligned Trim (Artifact-Free Stream Copy)

Find keyframe timestamps with ffprobe, then align your -ss exactly to a keyframe for a clean stream-copy cut.

# List I-frame (keyframe) timestamps
ffprobe -v quiet -select_streams v -skip_frame noref \
  -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

Align -ss to one of these timestamps:

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

5. Batch Trimming (Shell Script)

Trim multiple files at once with 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 place -ss relative to -i controls the speed/accuracy trade-off.

ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4
#       ↑ before -i
PropertyDetail
MechanismFast-seeks to the keyframe just before the specified time
SpeedVery fast — seconds even for large files
AccuracyRounds to keyframe boundary; may start slightly before specified time
Best forStream-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 copy output.mp4
#                   ↑ after -i
PropertyDetail
MechanismDecodes from the file start to the exact target frame
SpeedSlow — may take minutes for segments deep in a long file
AccuracyFrame-exact
Best forCases where output-side placement is unavoidable

Stream Copy vs. Re-Encode Comparison

MethodCommand SketchSpeedAccuracyFile Size
Stream copy (input-side -ss)-ss X -i in -to Y -c copy out★★★★★☆Unchanged
Re-encode (input-side -ss)-ss X -i in -to Y -c:v libx264 -crf 23 out★☆☆★★★Changes (per CRF)
Output-side -ss + stream copy-i in -ss X -to Y -c copy out★☆☆★★★Unchanged

Practical recommendation: Input-side -ss + -c:v libx264 -crf 23 gives the best balance.


Option Deep Dive

-avoid_negative_ts 1

Prevents playback issues in some players caused by negative PTS values when stream-copying mid-file segments.

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

-copyts

Preserves the original input timestamps in the output. Useful when you plan to concatenate clips later and need timestamps to stay consistent.

ffmpeg -ss 00:01:00 -i input.mp4 -t 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 shows green or black blocks.
Cause: The cut point is not a keyframe; the decoder has no reference frame to reconstruct the image.
Fix:

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

# Fix B: Find a nearby keyframe with ffprobe and use that timestamp for -ss

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

Symptom: -ss 00:01:00 -to 00:02:00 should give 1 minute but the output is shorter or longer.
Cause: With input-side -ss, the -to reference point can shift depending on FFmpeg version.
Fix: Use -t (duration) for predictable results:

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

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

Symptom: Output opens but only audio plays, or only video shows.
Cause: Source may lack the stream, or -an/-vn was passed unintentionally.
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 exits without error but the output file is 0 bytes.
Cause: The -ss value exceeds the total duration 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: Lips don’t match the audio in the trimmed clip.
Cause: The audio stream’s keyframe positions differ from the video stream’s.
Fix:

# Copy video, re-encode audio to resync
ffmpeg -ss 00:01:00 -i input.mp4 -t 60 -c:v copy -c:a aac output.mp4

FAQ

Q1. Can I place both -ss and -to before the input?
A. -to is an output option; it must come after -i. Only -ss and -t can appear before -i. Placing -to before -i may produce a warning and unexpected behavior.

Q2. Can I specify a frame number instead of a timestamp?
A. FFmpeg doesn’t accept frame numbers directly, but you can convert: frame ÷ frame_rate = seconds. Example: frame 600 at 30 fps → -ss 20.

Q3. Does stream copy degrade quality?
A. No. -c copy passes the raw audio/video data unchanged — quality is identical to the source, and the file size barely changes.

Q4. Does this work for H.265 (HEVC) video?
A. Yes. Stream copy (-c copy) preserves whatever codec is in the source. For re-encoding to H.265, replace the codec flag with -c:v libx265 -crf 28.

Q5. Does this work on Windows Command Prompt?
A. Yes, but backslash line continuation (\) doesn’t work in cmd.exe. Write the command on a single line, and quote paths that contain spaces:

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


Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner)
Primary sources: ffmpeg.org/ffmpeg.html / trac.ffmpeg.org/wiki/Seeking / ffmpeg.org/ffmpeg-formats.html