· 4 min read
ffmpeg -t vs -to: duration vs end position when encoding
Which FFmpeg option stops where, why -t wins when both are present, and why -ss A -i in -to B doesn't give you a B-A clip.
-t is a duration. -to is an end position. If you write both, -t wins and current FFmpeg builds print to stderr:
[out#0 @ 0x...] -t and -to cannot be used together; using -t.
The official docs are explicit on the precedence rule, repeating it under both options (doc/ffmpeg.texi line 825):
-to and -t are mutually exclusive and -t has priority.
Two complications follow. Position determines whether the option binds to input or output, and -ss resets the input timeline so -to no longer measures against the original file.
The commands below use bbb16.mp4 as shorthand for big_buck_bunny_720p_16sec.mp4 — a 16-second test clip. Substitute your own file, or download the sample once and reuse it.
Position decides input vs output
The same option name has two behaviors, picked purely by argv order. Both -t and -to are registered as OPT_INPUT | OPT_OUTPUT in fftools/ffmpeg_opt.c line 1669 — before -i they constrain how much input is read; before an output URL they constrain how much output is written.
For a single-input, single-output transcode that’s a distinction without a difference. It matters when you also use -ss for seek, because the input and output timelines stop matching.
The -ss trap
The most common surprise:
ffmpeg -ss 2 -i bbb16.mp4 -to 7 -c copy cut.mp4
This does not produce a 5-second clip. Run it against bbb16.mp4 and ffprobe -show_entries format=duration cut.mp4 reports ~7s for the file, while only ~5s actually plays. The official Trac Seeking wiki explains why (trac.ffmpeg.org/wiki/Seeking):
Note when -ss used before -i only: (-ss as input option) the timestamps will be reset according to 0. So -t and -to shall be the same.
With -ss before -i, FFmpeg seeks the input and rebases the output timeline so it starts at 0. -to 7 is then “stop at output-second 7,” not “stop at input-second 7.” You get 7 seconds of output (~5s of content plus a 2s negative-pts edit list that mp4 records, which is why ffprobe overstates the duration here).
The wiki’s own worked example is the same point in reverse: “use -ss 120 -i \"some.mov\" -to 60 alike to get the 1 min: from 120 s to (( 120 + 60 )) s. Not -to 180 for the 3 min starting at 120 s.”
This isn’t a documentation oversight. Carl Eugen Hoyos closed Trac ticket #9141 — “Input option -t/-to totally ignored when stream copying MPEG-TS recorded from TV” — with the same workaround: “Use the output option -t as a work-around.” The fix landed in commit 694545b (Shiwang Xie, committed by Gyan Doshi, July 2021).
Three patterns that always work
For “give me the segment from A to B,” pick by what you want to optimize:
| Pattern | Speed | What it means |
|---|---|---|
-ss A -to B -i bbb16.mp4 ... | Fast | Both options on the input side. Input seek + input stop. Timelines match. |
-ss A -i bbb16.mp4 -t (B-A) ... | Fast | Input seek + output duration. Unambiguous because -t is “duration” no matter the timeline. |
-i bbb16.mp4 -ss A -to B ... | Slow | Both on the output side. Decoder reads from 0 and discards until A. Exact, but pays the full read. |
The fast patterns are why people place -ss before -i. The trap is keeping -to on the output side after that move. Pair them.
-c copy cuts on keyframes
Every measured duration in the validation runs for this post drifted 0.01–0.17s from the requested value. That isn’t -t or -to misbehaving — -c copy aligns the cut to the previous keyframe and there’s nothing FFmpeg can do without re-encoding. Drop -c copy if you need exact frame boundaries; expect a slower run in exchange.
-copyts shifts what -to compares against
-copyts preserves input timestamps instead of rewriting them to start at 0. With it, -to is compared against the original input timeline, so -ss 2 -i bbb16.mp4 -to 7 does give you 5 seconds of content. The catch: the mp4 muxer still rewrites stream start_time to 0, so ffprobe will report ~7s for the file even when only ~5s plays. Use one of the three patterns above and ffprobe’s reading matches what plays.
Quick reference
-t= duration.-to= end position.-twins when both are present.- Before
-iconstrains input. Before the output URL constrains output. -ssbefore-iresets the input timeline to 0.-toafter-iis then measured against that reset clock, not the original file.- For “segment A to B,” prefer
-ss A -i in -t (B-A)or-ss A -to B -i in. Both fast, both unambiguous.