How to cut at exact frames using ffmpeg?

23

12

I'm trying to use ffmpeg to cut video files at precise times. The ffmpeg help shows an option -timecode_frame_start to specify the starting frame but I am unable to get this command to work. The resulting video always starts at the beginning of the original video. Here's an example of the command I'm running:

ffmpeg -i input.mpg -acodec copy -vcodec copy -timecode_frame_start 200 -vframes 210 -n ouput.mpg

I've moved the timecode_frame_start option before and after the other options with no change in results. Is there an additional option I need to specify? I've tried various file formats, mkv, avi, mp4, and it doesn't appear the problem is codec related. Here is one file I've tried:

http://www.seaotter.com/marine/movies/hermit-long-01.mpg

Am I missing something?

curmil

Posted 2012-08-09T00:26:27.553

Reputation: 615

Just wanted to note that I found a method for cutting at exact frames using melt, see Accurately cut video files from command line - Super User

– sdaau – 2018-01-26T02:26:31.440

appears this was answered on the mailing list (and NB that with -vcodec copy you can't "really" get frame specific cutting, since it can only resynchronize on i-frames – rogerdpack – 2012-08-09T11:46:17.080

@user39364 I asked on the mailing list and it turns out that this option doesn't do what the OP wants. I also learned something new :) – slhck – 2012-08-09T11:46:52.363

Answers

48

timecode_frame_start does not work like this.

Seeking based on frame numbers is not possible. The only way to start at specific frames is to convert a number of frames to ss.ms syntax, or hh:mm:ss.ms. So, if your video is at 25 fps, and you want to start at 133 frames, you would need to first calculate the timestamp:

133 / 25 = 5.32

Then run:

ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac out.mp4

Note that cutting on exact frames with bitstream copy (-c:v copy) is not possible, since not all frames are intra-coded ("keyframes"). A video must begin with a keyframe to be decoded properly. You will therefore have to re-encode the video, e.g. to H.264 using -c:v libx264 as shown above. You can also choose a lossless codec like -c:v ffv1 which preserves the quality of the input video.

To summarize, -ss will always be frame-accurate when performing re-encoding.

If you further want to encode a specific number of frames, use -frames:v, for example:

ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac -frames:v 60 out.mp4

Note that you you also have the choice to use the select/aselect filters to select frames/audio samples.

ffmpeg -i input.mp4 -vf 'select=gte(n\,100)' -c:v libx264 -c:a aac out.mp4

This, however, is slower than the -ss option shown above, since the entire video will be decoded.

slhck

Posted 2012-08-09T00:26:27.553

Reputation: 182 472

3for videos with drop frames (e.g. 29.97fps) that are over 10 minutes; how would you go about accurately calculating the time for a particular frame? – GFoley83 – 2016-09-05T20:53:06.083

1the select=gte(n\,100) method works but the seeking is eating up performance. If you test by encoding just 30 frames at a time, The further into the video I start, the longer ffmpeg takes to complete because of the seeking. – Adam Grant – 2017-01-29T09:32:16.343

After applying this method to a video file, in my player (VLC), there's some lingering audio that plays after the video frames have stopped playing. I'm thinking I need to somehow apply this same method to "audio frames". Or simply tell ffmpeg to halt adding more audio once the video has stopped. How do I do that? – t-mart – 2020-02-14T23:11:51.680

1@t-mart Add -shortest to make it stop encoding when the shortest stream is finished (i.e. the video stream in your case). – slhck – 2020-02-16T15:52:21.180

8

The option

-vf select=“between(n\,start_frame_num\,end_frame_num),setpts=PTS-STARTPTS"
e.g.,

-vf select=“between(n\,200\,300),setpts=PTS-STARTPTS"

cuts video from(includes) 200th to(includes) 300th frame, the sequence counting starts from 0.

Nuo Chen

Posted 2012-08-09T00:26:27.553

Reputation: 81