Frame-Anzahl mit ffmpeg abrufen

111

Weiß jemand, wie man mit ffmpeg die Anzahl der Frames aus einer Videodatei abruft? Die Renderausgabe von ffmpeg zeigt den aktuellen Frame und ich benötige die Frame-Anzahl, um den Fortschritt in Prozent zu berechnen.

Hansl
quelle
1
superuser.com/questions/84631/…
Ciro Santilli 3 冠状 冠状 病 六四 事件 3.

Antworten:

158

Hinweis: Das Vorhandensein einer Bearbeitungsliste in MP4 / M4V / M4A / MOV kann sich auf Ihre Bildnummer auswirken. Siehe Bearbeitungslisten unten.


ffprobe: Den Container abfragen

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Dies ist eine schnelle Methode.
  • Nicht alle Formate (wie Matroska) geben die Anzahl der Frames an, die zur Ausgabe von führen N/A. Siehe die anderen unten aufgeführten Methoden.

ffprobe: Zähle die Anzahl der Frames

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Dies ist eine langsame Methode.
  • Fügen Sie die -skip_frame nokeyOption hinzu, nur Keyframes zu zählen.

ffmpeg: Zähle die Anzahl der Frames

Wenn Sie nicht haben ffprobe, können Sie ffmpegstattdessen verwenden:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Dies ist eine etwas schnelle Methode.
  • Siehe gegen frame=Ende der Konsolenausgabe.
  • Fügen Sie die -discard nokeyEingabeoption (vorher -i) hinzu, um nur Keyframes zu zählen.

Listen bearbeiten

Ignorieren Sie die Bearbeitungsliste MP4 / M4V / M4A / MOV mit der -ignore_editlist 1Eingabeoption. Standardmäßig wird die Bearbeitungsliste nicht ignoriert.

Was die ffprobe-Optionen bedeuten

  • -v error Dadurch wird die Ausgabe "info" (Versionsinfo usw.) ausgeblendet, was das Parsen erleichtert.

  • -count_frames Zählen Sie die Anzahl der Frames pro Stream und melden Sie sie im entsprechenden Stream-Abschnitt.

  • -select_streams v:0 Wählen Sie nur den Videostream aus.

  • -show_entries stream=nb_framesoder -show_entries stream=nb_read_framesNur den Eintrag für nb_framesoder anzeigen nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Stellen Sie das Ausgabeformat (auch als "Writer" bezeichnet) auf ein default, drucken Sie nicht den Schlüssel jedes Felds ( nokey=1) und drucken Sie nicht die Kopf- und Fußzeile des Abschnitts ( noprint_wrappers=1). Es gibt kürzere Alternativen wie -of csv=p=0.

Siehe auch


Medieninformation

Das bekannte mediainfoTool kann die Anzahl der Frames ausgeben:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4Box

Für MP4 / M4V / M4A-Dateien.

MP4Box von gpac kann die Anzahl der Frames anzeigen:

MP4Box -info input.mp4

Beziehen Sie sich auf die Media InfoZeile in der Ausgabe für den fraglichen Videostream:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

In diesem Beispiel hat der Videostream 2525 Frames.


Boxdumper

Für MP4 / M4V / M4A / MOV-Dateien.

boxdumperist ein einfaches Tool von l-smash. Es wird eine große Menge an Informationen ausgegeben. Unter dem stszFeld sample_countfür die Stichprobengröße finden Sie die Anzahl der Frames. In diesem Beispiel hat der Eingang 1900 Videobilder:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Beachten Sie, dass eine Datei mehr als ein stszAtom haben kann.
llogan
quelle
5
Oder, wenn Sie mehr Geschwindigkeit wollen und wenn nb_frames zuverlässig genug ist, vereinfachen Sie als:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
Juanitogan
Dies gibt die Antwort zweimal für mich aus (dh 2600 \ n 2600). Gibt es einen bestimmten Grund dafür?
Jbodily
@jbodily Mein Beispiel oder Juanitogans? Ich kann es auch nicht duplizieren. Hier gibt es nicht viel zu arbeiten.
Llogan
+1, nicht zuletzt, weil im Gegensatz zu zu vielen anderen Antworten zu einem Befehlszeilen-Tool hier tatsächlich alle Befehlszeilenoptionen erläutert werden. Danke dir.
Ray
1
Beachten Sie, dass die erste Option, den Container abfragen, die Datei aufgrund von count_frames tatsächlich verarbeitet. Siehe @ juanitogans Kommentar.
aggieNick02
23

Unter Unix funktioniert dies wie ein Zauber:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
ataraxisch
quelle
3
Wirklich schön. Sie müssen den Audiostream nur nicht kopieren. Sie können -an instat verwenden.
rekire
1
@PrakharMohanSrivastava Überprüfen Sie diese Antwort
Antonio
4
Tatsächlich scheint dies schnell und zuverlässig zu sein:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Timothy Zorn
1
@ Michael danke für das Lächeln mit meinem Morgenkaffee :-)
Lloyd Moore
1
@ TimothyZorn Du hast meinen Tag gemacht!
Mladen Danic
13

Berechnen Sie es stattdessen anhand der Zeit.

Das ist, was ich tue und es funktioniert großartig für mich und viele andere.) Finden Sie zuerst die Länge des Videos im folgenden Ausschnitt:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

Sie sollten in der Lage sein, Duration: hh:mm:ss.nndie Größe des Quellvideoclips konsistent und sicher zu bestimmen. Anschließend können Sie für jede Aktualisierungszeile (CR, kein LF) den Text für die aktuelle Zeitmarke analysieren, in der er sich befindet:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

Seien Sie nur vorsichtig, um nicht immer eine perfekte Ausgabe von diesen Statuszeilen zu erwarten. Sie können Fehlermeldungen wie hier enthalten:

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

Sobald Sie die Zeit haben, ist es einfach zu rechnen : time / durration * 100 = % done.

Stu Thompson
quelle
1
Entschuldigen Sie, dass ich dumm bin, aber wie kann ich Zeit / Dauer tun, wenn die Dauer im Format hh: mm: ss.nn und die Zeit immer im Format xx.yy ist?
Omar Ali
2
@Omar, Als .NET-Entwickler erstelle ich daraus ein TimeSpanund verwende es dann currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). Die TimeSpan bietet auch eine leistungsstarke Analysefunktion, probieren Sie es aus
Shimmy Weitzhandler
Hervorragende Lösung, meine Zeit ist in hh: mm: ss: ms, also nehme ich an, dass FFMPEG in diesen 3 Jahren das Ausgabezeitformat verbessert hat.
ElektroStudios
1
Beachten Sie, dass in der Konsolenausgabe möglicherweise 29,97 angezeigt wird, dies steht jedoch für 30000/1001. Gleiches gilt für 23,98 (24000/1001) und 59,94 (60000/1001).
Llogan
Hinweis: Dies funktioniert (offensichtlich) nicht für Videos mit variabler Framerate.
Timothy Zorn
8

Nicht alle Formate speichern ihre Frame-Anzahl oder Gesamtdauer - und selbst wenn dies der Fall ist, ist die Datei möglicherweise unvollständig -, sodass ffmpeg keines von beiden standardmäßig genau erkennt.

Versuchen Sie stattdessen, bis zum Ende der Datei zu suchen und die Uhrzeit zu lesen. Zählen Sie dann die aktuelle Uhrzeit, während Sie unterwegs sind.

Alternativ können Sie versuchen, AVFormatContext->nb_index_entriesdie erkannte Dauer, die bei mindestens unbeschädigtem AVI / MOV einwandfrei funktionieren sollte, oder die Bibliothek FFMS2, die wahrscheinlich zu langsam ist, um sich um einen Fortschrittsbalken zu kümmern.

Alex seltsam
quelle
8

Versuchen Sie etwas wie:

ffmpeg -i "path to file" -f null /dev/null

Es schreibt die Frame-Nummer in stderr, sodass Sie den letzten Frame daraus abrufen können.

a1kmm
quelle
8

ffprobe Mit den folgenden Befehlen können Sie die Frame-Nummer abrufen

  1. erste Methode

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

die sagen, Daten im jsonFormat zu drucken

select_streams vSie werden ffprobeaufgefordert, uns nur videoStream-Daten zu geben. Wenn Sie diese entfernen, erhalten Sie auch audioInformationen

und die Ausgabe wird wie sein

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2. Sie können verwenden

ffprobe -v error -show_format -show_streams video_name

Wenn Sie ausgewählte Informationen wie die Bildrate wünschen, verwenden Sie den folgenden Befehl

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

Wenn Sie diese Methode verwenden, ist es möglich, dass Sie eine N/AAusgabe als erhalten.

Weitere Informationen finden Sie auf dieser Seite. FFProbe-Tipps

Hadi Rasekh
quelle
4

Versuche dies:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Julien
quelle
Funktioniert nicht mit dem *.ts. Die Ausgabe ist eine leere Zeile.
Victor Polevoy
3

Da mein Kommentar ein paar positive Stimmen bekam, dachte ich, ich würde ihn als Antwort belassen:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

Dies sollte schnell gehen, da keine Codierung durchgeführt wird. ffmpegwird einfach die Datei demuxen und den ersten Videostream so schnell wie möglich lesen (dekodieren). Der erste grepBefehl erfasst den Text, der den Rahmen zeigt. Der zweite grepBefehl erfasst nur die Nummer daraus. Der tailBefehl zeigt nur die letzte Zeile an (endgültige Frame-Anzahl).

Timothy Zorn
quelle
2

auf stus Antwort aufbauen. So habe ich die Bildrate für ein Video von meinem Handy gefunden. Ich habe den folgenden Befehl für eine Weile ausgeführt. Ich ließ die Frame-Anzahl auf ungefähr 10.000 steigen, bevor ich ungeduldig wurde und ^ C drückte:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

Dann habe ich zwei Informationen aus dieser Zeile abgerufen, die mit "frame =" beginnen, der Frame-Anzahl 7989 und der Zeit 00: 04: 26.30. Sie müssen zuerst die Zeit in Sekunden umrechnen und dann die Anzahl der Bilder durch Sekunden teilen, um "Bilder pro Sekunde" zu erhalten. "Bilder pro Sekunde" ist Ihre Bildrate.

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

Die Framerate für mein Video beträgt 30 fps.

Margaret
quelle
2

Das einzig genaue, was ich tun konnte, ist das Folgende:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

So stellen Sie sicher, dass dies mit Video funktioniert:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Lloyd Moore
quelle
Ich habe Ihre Antwort positiv bewertet, aber das funktioniert nur, wenn das Video kein Audio enthält. Wenn es enthält, wird dieses funktionieren:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

Entschuldigen Sie die Nekro-Antwort, aber vielleicht brauchen Sie diese (da ich für die letzten ffmpeg-Versionen keine Lösung gefunden habe.

Mit ffmpeg 3.3.4 habe ich Folgendes gefunden:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

Am Ende wird die Frame-Anzahl ausgegeben. Bei Videos mit Audio hat es bei mir funktioniert. Es gibt zwar zweimal eine "nb_frames" -Zeile, aber die erste Zeile war die tatsächliche Frame-Anzahl der von mir getesteten Videos.

acidrums4
quelle
Danke @ acidrums4. Verifiziert, dass diese Methode mit der neuesten Version von Github funktioniert, die ich heute erstellt habe.
Paul J
1

Ich benutze das php_ffmpeg, dann kann ich alle Zeiten und alle Bilder eines Films abrufen. Wie unten

$input_file='/home/strone/workspace/play/CI/abc.rmvb';
$ffmpegObj = new ffmpeg_movie($input_file);
echo $ffmpegObj->getDuration();
    echo $ffmpegObj->getFrameCount();

Und dann ist das Detail auf der Seite.

http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

xingyue
quelle
1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Gerard Wensink
quelle
Die Framerate wird normalerweise aus zwei Parametern berechnet. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Abgerundet durch ffmpeg auf: 23,98 Dauer = Stunden * 3600 + Minuten * 60 + Sekunden. Rest = 8177,91 Während Dauer Parameter = 8177,794625 Aber Rahmen = 24000/1001 * 8177,794625 = 196071 gibt die genaue Anzahl der Frames an. (Im Ernst).
Gerard Wensink
0

Linux

ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null

Rubin

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
Jaroslaw Malyk
quelle