Liste der Zeitstempel

Liste der Zeitstempel

Ich versuche, beispielsweise 10 Frames aus einem bestimmten Video auszuwählen, möglichst mit der größten Vielfalt und den meisten Szenen. Ich würde gerne mit verschiedenen Auswahlszenarien experimentieren, aber das Gute ist, dass der Begriff von I-frameautomatisch Szenenwechsel bedeutet! Ich würde also gerne die I-Frames erhalten. Aber vielleicht gibt es viele I-Frames, also muss ich sie wahrscheinlich abtasten.

Wie kann ich in FFMpeg oder Python die Liste aller Frame-Nummern von I-Frames in einem Video abrufen? Ich möchte die Liste verwenden, um nur 10 davon auszuwählen und sie als PNG/JPEG zu speichern.

Antwort1

Dies scheint ein X/Y-Problem zu sein, daher schlage ich mehrere verschiedene Befehle vor:

Liste der Zeitstempel

Wenn Sie für jedes Keyframe eine Liste mit Zeitstempeln ausgeben möchten:

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

Beachten Sie das -skip_frame nokey.

Filter auswählen

Eine weitere Methode ist die Verwendung vonFilter auswählenmit der sceneOption zur Ausgabe Ihrer Thumbnails:

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

Antwort2

Dadurch werden alle I-Frames als PNG-Bilder ausgegeben.

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

Diesem Kommentar ist eine ähnliche Frage von superuser.com zuzuschreiben. Wie extrahiere ich alle Keyframes aus einem Videoclip?

Hoffe, das hilft. Prost.

Ian

Antwort3

Erkenntnisse gewinnen durchHier, ich konnte es tun mit 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()

Antwort4

Um den Frametyp aller Frames im Video abzurufen, können Sie die folgende Python-Funktion verwenden. Siehe OriginallösungHier.

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

Ausgabeergebnis:

['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']

Wobei I und P der Rahmentyp sind.

verwandte Informationen