Search code examples
ffmpegblurkeyframe

Using blurdetect to filter blurred keyframes in ffmpeg5


I want to extract the keyframes of a video by ffmpeg and determine if each keyframe is blurred or not using a predefined thershold. I noticed the new blurdetect filter in ffmpeg5, so I tried the following command:

ffmpeg -i test.mp4 -filter_complex "select=eq(pict_type,I),blurdetect=block_width=32:block_height=32:block_pct=80" -vsync vfr -qscale:v 2 -f image2 ./I_frames_ffmpeg/image%08d.jpg

Using this command I can get the keyframes and at the end in the terminal I can see the average blur value of those frames being printed out. blur mean

My question is, can I use the blurdetect filter to get the blur value for each frame? Can I use this blur value as a precondition for keyframe selection, e.g. only select this frame as a keyframe if the blur value is less than 5?


Solution

  • Yes, blurdetect filter pushes the blur value of each frame to stream metadata, which you can capture with metadata filter. Try the following filtergraph:

    select=eq(pict_type,I),\
    blurdetect=block_width=32:block_height=32:block_pct=80,\
    metadata=print:file=-
    

    The metadata filter outputs to stdout, so you'll see 2 lines for each frame like:

    frame:1295 pts:1296295 pts_time:43.2098
    lavfi.blur=4.823009
    

    Note that the terminal may get cluttered with other logs, but these lines should be the only lines actually on stdout (standard logs are on stderr) so you should be able to capture easily. From there a simple regex should help you retrieve the blur values.

    Can I use this blur value as a precondition for keyframe selection, e.g. only select this frame as a keyframe if the blur value is less than 5?

    I believe (not verified) that metadata filter can do exactly this:

    metadata=select:key=lavfi.blur:value=5:function=less
    

    Not the best documentation, but it's all there