Instead of using -ss and -to seeking parameters, which seem not very accurate, can I cut videos for given frame numbers? For example;

ffmpeg -i video.webm -startingframe 80 -endingframe 560 output.webm

[80th frame and 560th frame included. So, as total it makes (560 - 80 +1) frames]

After the answers and a bit search, I have tried some commands. But so far I couldn't find an acceptable way.

If someone wants to cut video stream between 250th and 750th frames, this is the way to go. It will give 501 frames as output:

Note: movie.mp4 has 25 fps, and its audio sample rate 48k

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm

As expected, the output is 20 seconds long, exactly.

Using the same method for audio:

ffmpeg -i movie.mp4 -vn -af "aselect=between(n\,480\,1440),setpts=PTS-STARTPTS" a_stream.webm

Unexpectedly, this one has very poor accuracy. It should have given me 960001 (960k+1) samples which equal 20 seconds audio. But instead, the output was 20.505 seconds long and has 984240 samples. Also, if I increase the duration, error increases as well.

Then I tried to use -ss -to parameters for cutting audio stream:

ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm

The old classic way works much better. Output was 20.003 seconds long and has 960144 samples. Plus, increasing duration does not increase the error, the error is constant, there is always 144 samples surplus with that input file.

Summing up: select filter works well most of the time but a select is not. The classic -ss parameters work better for audio but not sample-accurate. Also, it is not possible to use -vf select and -ss parameters together, because -ss will affect both audio and video streams while we want it only affect audio.

So, to precisely cut a media file I have to do these 3 steps:

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm 
ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm 
ffmpeg -i v_stream.webm -i a_stream.webm -c:v copy -c:a copy  movie-between_10th_and 20th_seconds.webm

This gives the most accurate results. Video is 20.000 seconds long and frame-acurate Audio is 20.003 seconds long and has 960144 sample. Not exactly matches with the video stream, but it is OK. There is only 144 samples surplus. The biggest downside is, whenever I want to cut a file, I have to send 3 commands for a simple job and it creates two unnecessary files: a_stream.webm and v_stream.webm. And the select filter is not working on some input files I have tried. It does the job successfully (?) but never stops the encoding process, so I have to close command prompt every time.

  • I have read that page before I posted this question. That page didn't help me. If an input has variable fps can we simply calculate by using that equation? I dont think so. Also still I don't think '-ss' will give me accurate position. Frame by frame seeking would be better I guess. – destor Jan 18 '15 at 4:04
  • Note that -ss is frame-accurate (see here). Do you actually have variable-fps input? My answer links to the mailing list thread which mentions using select filters where you can specify the frame number. Have you tried that? – slhck Jan 18 '15 at 10:25
  • I have tried using select and aselect filters for video and audio streams. Select is frame-accurate for video, but aselect is not sample-accurate. Actually it is far from being accurate. It gives much more worse results than using the simple -ss -to paramaters. Because of that, for now, i use combination of select filter and -ss -to parameters to achive most accurate cutting. But it is a grungy way to do it. Please look at my first post i have added some commandlines and their results – destor Jan 21 '15 at 1:35
  • ffmpeg version? – fie Mar 15 '17 at 13:54
  • Why are you trying to cut by a frame number anyhow. If one needs that sort of accuracy then why not use avidemux? Also maybe your original problems are because it selects the closest key frame? – fie Mar 15 '17 at 14:08

Audio comes from seconds, not frames, so if you want to cut a video you have to calculate video fps × 20 second like this: 20 second of 23.97 fps = 479.4

Frame cutting is not accurate because you can't get full fps for the last second, so the audio will get more seconds or only a half second or a bit more or less!  Maybe you should use seconds instead of frames to get exact cut you tell the ffmpeg to do it for you.  And if you get 1 extra frame, what about to change 250th and 750th frames to 250th and 749th frames?!  Use minus 1 there to always get how many frames you ask for!

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.