2

I am trying to split a video video.avi (with N being the total number of frames) into contiguous chunks according to a fixed number of frames (say M = 100). Specifically this process should yield:

  1. video_0.avi: Frames 0 to M-1
  2. video_1.avi: Frames M to 2M-1
  3. video_2.avi: Frames 2M to 3M-1
  4. ...

It is important that each chunk video_*.avi has exactly M frames. Therefore, the last chunk can be discarded if N is not divisible by M.

I found related issues (e.g. Split video file into pieces with ffmpeg) but find myself struggling to replace the specification in seconds with the number of frames.

4
  • 2
    With codecs such as H.264 there isn't really a hard relationship between frames and time. There are incremental pre-frames and incremental post-frames, with a full reference frame only every so often. You can't easily chop during a pre-frame section because the reference frame on which these pre-frames depend hasn't yet been encountered. Commented Jan 28, 2022 at 10:40
  • You can only split by I frames and as @roaima has mentioned there's no guarantee they are evenly spread. Commented Jan 28, 2022 at 11:03
  • Okay thank you very much to both of you! Commented Jan 28, 2022 at 11:11
  • "With codecs such as H.264 there isn't really a hard relationship between frames and time" -- can you name one that is? That's what I'm actually trying to find out, so that I can convert a video to a format where I can split it without the headache that H264/H265 are causing
    – user69136
    Commented Mar 26, 2022 at 20:10

1 Answer 1

1

For the first chunk, you should be able to use -vframes M-1 and it will be OK (even for -c copy if I recall).

The other chunks are trickier, and I've had no success with: -vf 'select=gte(n\,M)' -- it needs re-encoding anyway, but does strange things with different codecs -- e.g. leaves the preceding duration with a still frame, and plays the sound...

You can get the time in seconds by dividing the frame numbers through FPS, e.g. if your FPS is $fps and M is $M:

ffmpeg -i video.avi -ss `echo "scale=6; $M / $fps" | bc` -to `echo "scale=6; (2 * $M) / $fps" | bc` video_01.avi

etc. If you have a scripting language to compute these times, it will be easier. Also, note that when re-encoding (i.e. without -c copy), -ss and -to will be precise, see also: https://superuser.com/questions/459313/how-to-cut-at-exact-frames-using-ffmpeg

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .