在 FFMPEG / Python 中获取视频中的 I 帧列表

Tin*_*a J 6 video python ffmpeg iframe video-encoding

我试图从给定视频中选择 10 个帧,可能具有最高的多样性和场景。我想尝试各种选择场景,但好处是,I-frame本质上意味着场景变化的概念!所以我想获得 I 帧。但也许有很多 I 帧,所以我可能必须对它们进行采样。

如何在 FFMpeg 或 Python 中获取视频中所有 I 帧的frame_number 列表?我想使用列表仅选择其中 10 个并将它们另存为 PNG/JPEG。

llo*_*gan 6

这看起来像是一个 X/Y 问题,所以我将提出几个不同的命令:

时间戳列表

如果要输出每个关键帧的时间戳列表:

ffprobe -v error -skip_frame nokey -show_entries frame=pkt_pts_time -select_streams v -of csv=p=0 input
0.000000
2.502000
3.795000
6.131000
10.344000
12.554000
Run Code Online (Sandbox Code Playgroud)

请注意-skip_frame nokey.

选择过滤器

另一种方法是使用选择过滤器以及scene输出缩略图的选项:

ffmpeg -i input -vf "select=gt'(scene,0.4)',scale=160:-1" -vsync vfr %04d.png
Run Code Online (Sandbox Code Playgroud)


Tin*_*a J 1

这里获得见解,我能够做到这一点ffprobe

def iframes():
    if not os.path.exists(iframe_path):
        os.mkdir(iframe_path)
    command = 'ffprobe -v error -show_entries frame=pict_type -of default=noprint_wrappers=1'.split()
    out = subprocess.check_output(command + [filename]).decode()
    f_types = out.replace('pict_type=','').split()
    frame_types = zip(range(len(f_types)), f_types)
    i_frames = [x[0] for x in frame_types if x[1]=='I']
    if i_frames:
        cap = cv2.VideoCapture(filename)
        for frame_no in i_frames:
            cap.set(cv2.CAP_PROP_POS_FRAMES, frame_no)
            ret, frame = cap.read()
            outname = iframe_path+'i_frame_'+str(frame_no)+'.jpg'
            cv2.imwrite(outname, frame)
        cap.release()
        print("I-Frame selection Done!!")


if __name__ == '__main__':
    iframes()
Run Code Online (Sandbox Code Playgroud)