Bhinish Dhiman
Trimming video without re-encoding: where the cut actually lands
A copy-only trim begins at a keyframe. At 0.1-second steps across six files, the requested start was hit exactly in 0.5% to 9.2% of cases; the mean gap was 4.06 s on x264 defaults, 0.96 s at a 2 s keyframe interval and 0.46 s at 1 s. The extra frames stay in the file; an edit list hides them.
Every lossless trimmer says the cut snaps to a keyframe. None of them say by how much, on a file you would actually have. We measured it on six.
Two terms
A keyframe is a frame stored as a complete picture. Every frame between two keyframes is stored as a difference from its neighbours, so a decoder that starts anywhere else has nothing to apply the differences to. A copy-only trim moves encoded packets into a new container without decoding them; it cannot start mid-difference, so the real start of the copy is the last keyframe at or before the point you asked for.
The measurement
We generated five files with FFmpeg 6.0 and recorded a sixth with Chromium: a 60-second clip encoded with x264’s defaults at 30 fps (keyframe every 250 frames); the same clip with keyframes forced every 1 s and every 2 s; a 42-second slideshow of fourteen photographs with x264’s scene-cut detection left on; the slideshow as VP9 in WebM with a 240-frame interval; and a 9-second recording of two pages on this site, as Playwright writes it. For each file we asked mediabunny’s EncodedPacketSink.getKeyPacket() — the call behind the figure our trim tool prints — for the keyframe before every point from 0 to the end in 0.1 s steps, and recorded the gap. 2,730 requests in total, on 1 October 2026.
| File | Keyframe interval | Mean gap | Median | 90th percentile | Largest | Exact | Over 1 s |
|---|---|---|---|---|---|---|---|
| x264 defaults, 30 fps | 8.33 s | 4.06 s | 4.03 s | 7.47 s | 8.30 s | 0.5% | 86.5% |
| Keyframe every 1 s | 1.00 s | 0.46 s | 0.50 s | 0.90 s | 1.00 s | 9.2% | 0% |
| Keyframe every 2 s | 2.00 s | 0.96 s | 1.00 s | 1.80 s | 2.00 s | 4.5% | 49.0% |
| Slideshow, scene cuts every 3 s | 3.00 s | 1.46 s | 1.50 s | 2.70 s | 3.00 s | 2.9% | 65.7% |
| VP9 WebM, 240-frame interval | 8.00 s | 3.83 s | 3.80 s | 7.10 s | 8.00 s | 1.2% | 85.2% |
| Chromium screen recording, VP8 | 5.12 s | 2.29 s | 2.28 s | 4.30 s | 5.10 s | 1.1% | 76.7% |
The mean gap is half the keyframe interval, as it must be for a uniformly chosen point. The number worth carrying is the last column: on a file with x264’s default settings — which is what most desktop exports are — more than four cuts in five begin over a second before the point you chose.
What is in the file, and what a player shows
We then ran the copy itself, with the same Conversion configuration as the tool, asking for 10.0 s to 15.0 s from the x264-defaults file. The nearest keyframe was at 8.333 s. The output held 200 frames — 6.67 seconds of video — but it also carried an edit list, an MP4 instruction that tells the player where the presentation begins. FFmpeg decoded 150 frames from it and reported 5.00 s. Chromium’s video element reported a duration of 5.000 s. Told to ignore the edit list, FFmpeg decoded all 200 and reported 6.67 s.
So the answer to “where does the cut land” has two halves. The bytes begin at the keyframe: 1.67 s of picture you did not ask for is in the file, and it is why the output is larger than the fraction you kept. The presentation begins where you asked, in any player that honours edit lists, which in our test included Chromium and FFmpeg. A player or editor that ignores them shows the extra 1.67 s and appears to have trimmed the wrong place.
Against re-encoding
| Copy-only | Decode and re-encode | |
|---|---|---|
| Start point | Keyframe; presentation trimmed by edit list | Any frame |
| Picture | Identical bytes | Generation loss, worst on the second pass |
| Time for a 1080p clip | Bounded by reading the file | Bounded by encoding it |
| Encoder required | None | A working video encoder |
| Extra frames in the file | Up to one keyframe interval | None |
What decides the number for your file
The keyframe interval is set by whatever encoded the file. Streaming-oriented exports are typically set to one or two seconds, because a player seeking into a stream faces exactly the constraint a trimmer does. x264’s default is 250 frames, and screen recorders often use longer intervals still, because a static desktop compresses so well that keyframes look expensive. There is nothing a trimmer can do about it after the fact except measure and say so — which is why our tool looks up the real keyframe for the point you set and prints the gap before you press the button.