Checking keyframe interval?

34,950

Solution 1

You can display the timestamp for each frame with ffprobe with awk to only output key frame info. Works in Linux and macOS.

ffprobe -loglevel error -select_streams v:0 -show_entries packet=pts_time,flags -of csv=print_section=0 input.mp4 | awk -F',' '/K/ {print $1}'

Or a slower method that works on any OS and does not require awk or similar additional processing tools:

ffprobe -loglevel error -skip_frame nokey -select_streams v:0 -show_entries frame=pkt_pts_time -of csv=print_section=0 input.mp4

Results:

0.000000
2.502000
3.795000
6.131000
10.344000
12.554000
16.266000
17.559000
...

See the ffprobe documentation for more info.

Solution 2

The following command will give you the offsets of all key Frames in the Video

ffprobe -show_frames -select_streams v:0 \
        -print_format csv Video.mov 2> /dev/null |
stdbuf -oL cut -d ',' -f4 |
grep -n 1 |
stdbuf -oL cut -d ':' -f1

Note that the command might respond a little late. Have patience :-)

The ffprobe command gives you the frame level details in CSV format. Rest is a smart combination of cut and grep commands.

cut -d ',' -f4

filters the fourth column - this refers to the 'key_frame' flag.

grep -n 1

filters the key-frames only, and shows their line numbers in the CSV feed.

The

stdbuf -oL

with the cut command manipulates the buffer of the cut command.

Share:
34,950
rabotalius
Author by

rabotalius

Updated on July 13, 2022

Comments

  • rabotalius
    rabotalius almost 2 years

    How can I check keyframe interval of a video file?

    all I can see in ffmpeg output is:

      Metadata:
        metadatacreator : Yet Another Metadata Injector for FLV - Version 1.8
        hasKeyframes    : true
        hasVideo        : true
        hasAudio        : true
        hasMetadata     : true
        canSeekToEnd    : true
        datasize        : 256600272
        videosize       : 210054362
        audiosize       : 45214634
        lasttimestamp   : 5347
        lastkeyframetimestamp: 5347
        lastkeyframelocation: 256649267
      Duration: 01:29:07.24, start: 0.040000, bitrate: 383 kb/s
        Stream #0:0: Video: h264 (High), yuv420p, 720x304 [SAR 1:1 DAR 45:19], 312 kb/s, 25 tbr, 1k tbn, 50 tbc
        Stream #0:1: Audio: mp3, 44100 Hz, mono, s16p, 64 kb/s
    
  • lucky1928
    lucky1928 almost 9 years
    per my understand, select first video stream command should be -select_streams v:0, but not 0:v:0. am I wrong?
  • llogan
    llogan almost 9 years
    @lucky1928 You're correct. I fixed the typo (0:v:0 would be the syntax in ffmpeg).
  • voices
    voices about 7 years
    Is the keyframe interval included in this output, somewhere? I can't see it.
  • maetthu
    maetthu over 6 years
    It isn't directly, but you can calculate the keyframe interval from this output. Count the frames from one keyframe (key_frame=1) to the next, this is the interval in frames. If you want the keyframe interval in seconds, multiply it by the framerate. Note that it may not be constant and can be different for each keyframe depending on the encoding parameters. A quick and dirty way to determine the interval for the first two keyframes: ffprobe -select_streams v:0 -show_frames INPUT.MP4 2>/dev/null | awk -vf=0 '/key_frame=1/ {f=1; ++d} d!=2 && /key_frame/ {print} f && d==2 {exit}' | wc -l
  • Multihunter
    Multihunter about 6 years
    Does it bother anyone else that the -skip_frame flag isn't mentioned in the documentation anywhere? How are we supposed to know about it if it's not in the documentation?
  • llogan
    llogan about 6 years
    @Multihunter It is, but it is buried in ffmpeg-all. See man ffmpeg-all or the online ffmpeg-all documentation. Alternatively, refer to ffmpeg -h full.
  • tmm1
    tmm1 almost 5 years
    This command will be very slow as it is decoding every frame. You can use -show_entries packet=pts,flags for a much faster result and filter for flags=K
  • llogan
    llogan almost 5 years
    @tmm1 Thanks, added.
  • Francois Bertrand
    Francois Bertrand over 2 years
    The Windows/cross-platform command provided did NOT work properly, had to change frame=pkt_pts_time to frame=pts_time, as nothing was showing up. The field may have changed the name since the original post?