I'm trying to get the frames of a video file as images, together with tags that if the frame is a I, P or B frame.

I know that ffmpeg can output only a specific type of frame using select

For I-Frames one can do: ffmpeg -i input.mp4 -vf "select='eq(pict_type,PICT_TYPE_I)'" -vsync vfr iframe_%04d.png

Other pict types can be used for B or P frames. However this will output the frames as iframe_0001.png, iframe_0002.png, etc. The original frame number in the video is lost.

For example, to achieve something like: iframes_0001.png, bframe_0002.png, bframe_0003.png, pframe_0004.png, bframe_0005.png, iframe_0006.png, ...

It's ok if several passes are required, it's also ok to generate an auxiliary file that specifies the type of frame it is (maybe a text file with frame number and frame properties).



ffmpeg -i input.mp4 -filter_complex "setpts=N/TB,select='1*eq(pict_type,PICT_TYPE_I)+2*eq(pict_type,PICT_TYPE_P)+3*eq(pict_type,PICT_TYPE_B)':n=3[i][p][b]" -vsync 0 -map "[i]" -r 1 -frame_pts 1 iframe_%04d.png -map "[p]" -r 1 -frame_pts 1 pframe_%04d.png -map "[b]" -r 1 -frame_pts 1 bframe_%04d.png

The select filter can generate multiple outputs at once. Which output a frame is sent to, depends on the evaluated value of the expression. The expression above will evaluate to either 1, 2 or 3 depending on the frame type and get sent to the first, second or third output respectively. These three outputs are then mapped to different outputs.

The frame_pts option makes the filenames contain the frame timestamp. Before the select filter, setpts filter is added to make the frame timestamps 1 second apart. -r 1 is added to each output so that the filenames are as expected. See Extract I-frames to images quickly for why.

  • 1
    A little explanation on the parameters passed? – moodoki Sep 9 '19 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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