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
- The meaning and usage of
-ss,-to, and-t - Input-side
-ssvs. output-side-ss— speed vs. accuracy trade-off - Stream-copy fast trimming and how to fix keyframe artifacts
- Frame-accurate trimming with re-encoding
- Extracting multiple segments in one command
- Finding keyframe positions with ffprobe before cutting
- Batch trimming with a shell script
- Five common errors and how to fix them
- Five frequently asked questions
Quick Reference
| Option | Position | Meaning | Example |
|---|---|---|---|
-ss position | Before or after -i | Start position (absolute timestamp) | -ss 00:01:30 |
-to position | Before output file | End position (absolute from file start) | -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 |
-toand-tcannot be used together. If both are specified,-twins (per the FFmpeg docs).
Time Formats
FFmpeg accepts two time formats interchangeably.
| 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) |
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.
Input-Side -ss (Recommended for Most Cases)
ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -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 copy 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 |
Stream Copy vs. Re-Encode Comparison
| Method | Command Sketch | Speed | Accuracy | File 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"
Related Articles
- Concatenating Video — When to Use concat demuxer vs. concat filter
- FFmpeg Basic Syntax and Options
- Video Compression — CRF Mode vs Bitrate Mode
- Inspect Metadata and Stream Info with ffprobe
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