ffmpeg: cut videos to the exact frame

!
Warning: This post is over 365 days old. The information may be out of date.

When cutting videos using ffmpeg using the following command:

ffmpeg -i input.mp4 -ss 00:00:24.183 -to 00:03:22.183 -c copy output.mp4

You may notice that ffmpeg may sometimes not cut the video to the correct frame. It may start a bit later than the time specified, 00:00:24.183, by a couple of frames or a couple of seconds. Worse yet, the video may appear frozen until it reaches the arbitrary frame ffmpeg started on, upon which it will start playing normally. What gives?

Well, it all comes down to keyframe types (again, if you’ve seen my previous posts about ffmpeg), but the short gist of it is that certain keyframes (P-frames and B-frames) rely on I-frames in order to render. So if your supplied timecode does not start on a I-frame, ffmpeg skips over until it finds the first I-frame, then repeats that to the start of the video, like this:

Original file:

IPPPBIPPPBIPPPBIPPPB
       ^ Your supplied start timecode

Where ffmpeg will start:

----------IPPPBIPPPB
          ^

What ffmpeg will do for the missing frames:

-------IIIIPPPBIPPPB

Finally cut down to size:

IIIIPPPBIPPPB

So how do we tell ffmpeg to just re-encode based on the previous I-frame, before your start timecode? Well, do you see the -c copy parameter in the original command? That’s what’s causing the issue. The parameter tells ffmpeg to copy the file without re-encoding anything, which is fast, but it won’t let ffmpeg re-encode by rendering the frames on top of each other. The solution is to just replace that parameter with a instruction to re-encode with an encoder:

ffmpeg -i input.mp4 -ss 00:00:24.183 -to 00:03:22.183 -c:v libx264 -crf 18 output.mp4

Related Posts

comments