FFmpeg: Trim an MP4 (No Re-Encoding)
Stream-copy trims an MP4 between two timestamps without re-encoding. Output is bit-identical to the source — instant on any machine.
Command
ffmpeg -ss 00:00:10 -i input.mp4 -to 00:00:30 -c copy -y output.mp4What each flag does
| -ss | Seek to this timestamp (HH:MM:SS or seconds). Place BEFORE -i for fast keyframe seek; AFTER -i for sample-accurate seek. |
|---|---|
| -i | Input file. Can be a video, audio, or image. Repeat for multiple inputs. |
| -to | Stop at this timestamp (absolute, not duration). Use -t instead for a relative duration. |
| -c copy | Stream-copy: no re-encoding. Output is bit-identical between cut points. Fastest possible. |
| -y | Overwrite output file without confirmation. |
Notes & gotchas
- Place -ss BEFORE -i for fast keyframe seek. AFTER -i is sample-accurate but slower.
- -to is the absolute end time. Use -t 20 for "encode 20 seconds starting from -ss" instead.
- Stream-copy snaps to the nearest keyframe, which can offset the start by up to ~10 seconds in long-GOP video. Re-encode for frame-accurate cuts.
Check it worked
ffprobe -v error -show_entries format=duration -of csv=p=0 output.mp4Around 20 seconds for the example. A duration much longer than requested means the seek landed on the wrong keyframe.
What to change
| Move the -ss before -i, or after it | Before the input is a fast seek and lands on the nearest keyframe. After the input is exact and decodes everything up to that point, which is slow on a long file. |
|---|---|
| -to versus -t | -to is an absolute timestamp in the output, -t is a duration. Mixing them up is the usual reason a clip is the wrong length. |
| Drop -c copy | Re-encoding gives you the exact frame you asked for instead of the nearest keyframe, at the cost of time and one generation of quality. |
If it fails
The clip starts several seconds before the timestamp you asked for.
Why: Stream copy cannot cut mid-frame, so it snaps back to the nearest keyframe. Long-GOP encodes from phones and screen recorders can space keyframes ten seconds apart.
Fix: Drop -c copy and let it re-encode, which cuts exactly where you asked, or move -ss after -i to trade speed for accuracy.
The output plays but the first second is frozen or black.
Why: The cut began on a frame that depends on data before it, so the decoder has nothing to build the first frames from.
Fix: Re-encode the first few seconds instead of stream-copying, or start the cut on an earlier keyframe.