How to cut at exact frames using ffmpeg?
Solution 1
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.
Solution 2
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.
Solution 3
LosslessCut is a cross-platform GUI tool that uses FFmpeg as a backend and losslessly cuts your video. You can choose to cut at a keyframe or any frame.
Related videos on Youtube
curmil
Updated on September 18, 2022Comments
-
curmil almost 2 years
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?
-
slhck almost 12 years@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 :)
-
tetram over 6 yearsJust 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
-
-
GFoley83 almost 8 yearsfor 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?
-
D. Go. over 7 yearsthe
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. -
t-mart over 4 yearsAfter 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?
-
slhck over 4 years@t-mart Add
-shortest
to make it stop encoding when the shortest stream is finished (i.e. the video stream in your case). -
mLstudent33 over 4 yearsbash: syntax error near unexpected token `('
-
Kingsley almost 4 yearsWhat does
setpts=PTS-STARTPTS
do? -
Link-akro almost 4 yearsI agree with your suggestion (and i virtually had such an idea years ago). Such a feature should be provided with options. Before such a feature exists we might manage to do it with shell scripts but I'd rather avoid the troubles such as shell compatibility. I am concerned that codecs or muxers might not support well a variability in the rate (conversely delay) of key frames near the extremities. I learnt recently about Instantaneous Decode Refresh frames and their opposite whatsoever which may cause troubles like interrupted buffered video streams on internet.
-
Michael over 3 yearshow can i trim at an exact frame but only re-encode from the starting frame until the first keyframe after that, then copy?
-
slhck over 3 years@Michael You can't. If you use the
select
ortrim
filters, everything is re-encoded. If you do a bitstream copy via-c copy
then you can't selectively re-encode. You could try to splice the videos into pieces and merge them with the concat demuxer: trac.ffmpeg.org/wiki/Concatenate#demuxer — this may work if you have the exact same codec and codec settings. -
SUMIT over 3 yearsFor reference, here's the documentation on ffmpeg filters: ffmpeg.org/ffmpeg-filters.html. In particular, see the section on Multimedia Filters for descriptions of the select and setpts filters (as at 15 Jan 2021 sections 16.14 and 16.16, respectively).
-
matthew-e-brown over 2 yearsI don't think this is the case. LosslessCut's README states that it rounds to nearest keyframe.