Trim and cut video with FFmpeg: precise timestamps without re-encoding
Cut clips from longer videos via stream-copy when keyframe boundaries align, or with re-encoding when frame-accurate cuts matter. The seek-input trick that saves real time.
When to use this
You trim or cut video for clip extraction (highlight reels, social-media segments, episodic delivery from a master), removing intro/outro from production deliverables, or cutting bad takes from raw footage. Two distinct techniques: stream-copy (instant, but cuts on keyframe boundaries only — typically every 2 seconds) and re-encode (frame-accurate but slower). Pick stream-copy when the source has frequent keyframes and you can tolerate ±1 second of drift; pick re-encode when the cut needs to land on a specific frame.
Command variants
ffmpeg -ss 00:00:30 -to 00:01:30 -i input.mp4 \
-c copy \
output.mp4-ss BEFORE -i seeks the input first (faster). Cut snaps to nearest keyframe — for sources with 2-second GOPs, drift is ≤2 seconds.
ffmpeg -i input.mp4 -ss 00:00:30 -to 00:01:30 \
-c:v libx264 -preset fast -crf 22 \
-c:a aac -b:a 192k \
output.mp4-ss AFTER -i for accurate seeking. Cut lands on the exact specified frame at the cost of re-encoding (~5-10× slower).
# Generate parts:
ffmpeg -ss 00:00:10 -to 00:00:20 -i input.mp4 -c copy part1.mp4
ffmpeg -ss 00:00:40 -to 00:00:50 -i input.mp4 -c copy part2.mp4
# Concat:
echo "file 'part1.mp4'" > files.txt
echo "file 'part2.mp4'" >> files.txt
ffmpeg -f concat -safe 0 -i files.txt -c copy highlights.mp4For highlight reels with multiple clips, cut each segment then concat. Stream-copy throughout = near-instant.
What each parameter does
-ss [time]Seek to time. Position before -i for fast seek (keyframe-bounded); position after -i for accurate seek (decodes to exact frame).
-to [time]Stop at time. Together with -ss defines the cut window.
-t [duration]Alternative to -to: specify duration instead of end time. Useful when you know clip length, not end timestamp.
-c copyStream-copy. Cut without re-encoding. Fastest but keyframe-bounded.
What this outputs
A trimmed video file. Stream-copy mode produces output identical in quality to the source; re-encode mode produces output at the encoder settings you specify (typically slightly different file size and quality from source).
Pitfalls
- Stream-copy with mismatched keyframe alignment produces audio/video desync at the cut point. Verify the source has frequent keyframes (closed GOPs every 2 seconds) before stream-copy cutting.
- -ss BEFORE -i is faster but inaccurate; -ss AFTER -i is accurate but slower. Easy to mix up — they're semantically different operations.
- Some MOV/MP4 files have non-zero start timestamps (e.g., starting at 1 hour for a multi-hour broadcast). -ss interprets relative to file start, not video start.
- Audio-only or video-only cuts: -ss before -i applies to all streams; -ss after -i can be applied per-stream with -map. Read closely if you need stream-specific cuts.
- Cut tolerance for HLS-style content: HLS segment cuts must align with segment boundaries (typically 2-4s). Cutting mid-segment produces unplayable output for some players.
At production scale
Stream-copy trimming is essentially free at scale (I/O-bound, not compute). Re-encode trimming runs at libx264-medium speeds, ~5-10× slower than real-time. For workflows generating many short clips from long sources (sports highlights, news clips), structure pipelines so stream-copy is the default and re-encoding is the exception. At >100K cuts/day, the difference compounds.
MpegFlow models trimming as a parameterized DAG stage with stream-copy vs re-encode chosen automatically based on cut precision needed. The audit log records both the requested cut points and the actual frame boundaries used, so QC can verify when stream-copy drift is acceptable.
- FFmpeg
- trim
- cut
- editing
- video-operations