Получить список I-кадров в видео в FFMPEG / Python

Я пытаюсь выбрать, скажем, 10 кадров из данного видео, возможно, с самым большим разнообразием и сценами. Я хотел бы поэкспериментировать с различными сценариями выбора, но хорошо то, что понятие I-frame по сути означает изменение сцены! Поэтому я хотел бы получить I-кадры. Но, может быть, есть много I-кадров, так что, вероятно, мне придется их попробовать.

Как я могу получить список всех frame_number I-кадров в видео в FFMpeg или Python? Я хотел бы использовать список, чтобы выбрать только 10 из них и сохранить их в формате PNG/JPEG.

4 ответа

Решение

Получив понимание отсюда, я смог сделать это с 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()

Это похоже на проблему 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

Обратите внимание -skip_frame nokey,

выберите фильтр

Другой метод заключается в использовании фильтра выбора с scene опция для вывода ваших миниатюр:

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

Это выведет все i-кадры в виде изображений PNG.

ffmpeg -i 2.flv -vf "select=eq(pict_type\,I)" -vsync vfr frame-%02d.png

Отнесите к этому комментарию аналогичный вопрос usersuper.ru. Как извлечь все ключевые кадры из видеоклипа?

Надеюсь, это поможет. Приветствия.

Ян

Чтобы получить тип кадра для всех кадров видео, вы можете использовать следующую функцию Python. Смотрите оригинальное решение здесь .

      def get_frames_metadata(file):
    command = '"{ffexec}" -show_frames -print_format json "{filename}"'.format(ffexec='ffprobe', filename=file)
    response_json = subprocess.check_output(command, shell=True, stderr=None)
    frames = json.loads(response_json)["frames"]
    frames_metadata, frames_type, frames_type_bool = [], [], []
    for frame in frames:
        if frame["media_type"] == "video":
            video_frame = json.dumps(dict(frame), indent=4)
            frames_metadata.append(video_frame)
            frames_type.append(frame["pict_type"])
            if frame["pict_type"] == "I":
                frames_type_bool.append(True)
            else:
                frames_type_bool.append(False)
    print(frames_type)
    return frames_metadata, frames_type, frames_type_bool

Результат вывода:

      ['I', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'I', 'P']

Где I и P — это тип кадра.

Другие вопросы по тегам