Wie erhalte ich die Anzahl der Frames in einem Video in der Linux-Befehlszeile?

30

Ich habe eine Videodatei und möchte die Anzahl der darin enthaltenen Videoframes ermitteln. Ich kann verwenden ffmpeg, um die Länge des Videos und die FPS zu erhalten. Allerdings sehe ich für die Gesamtzahl der Frames nichts Offensichtliches.

Theoretisch sollte man in der Lage sein, die Länge (in Sekunden) mit der FPS zu multiplizieren, um die Anzahl der Frames zu erhalten, aber in diesem Fall geben die Länge (34,43 Sekunden) und die Framerate (29,97 fps) eine Nicht-Ganzzahl an, was mich zu einer Zahl macht denke, ich mache etwas falsch.

Ich muss in der Lage sein, dies in der Befehlszeile auf eine vollständig automatisierte und nicht grafische Weise zu tun. Ich brauche das auch, um ziemlich genau zu sein und keine Schätzung (wenn das überhaupt mit Videodateien möglich ist)

Ich habe versucht, tcprobeauf einige Dateien zu verwenden. Für einige AVI-Dateien funktioniert es, aber für einige VOB-Dateien hat die Ausgabe von tcprobe nicht die Anzahl der Frames. Ich bekomme diese Ausgabe:

[tcprobe] MPEG program stream (PS)
[tcprobe] summary for myfile.vob, (*) = not default, 0 = not detected
import frame size: -g 720x480 [720x576] (*)
     aspect ratio: 4:3 (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
                   PTS=2199.3972, frame_time=33ms bitrate=7000 kbps
      audio track: -a 0 [0] -e 48000,16,5 [48000,16,2] -n 0x2000 [0x2000] (*)
                   PTS=2199.2763, bitrate=192 kbps
                   -D 3 --av_fine_ms 20 (frames & ms) [0] [0]
Rory
quelle
Ihre Gleichung gibt Ihnen eine gute Schätzung des Baseballstadions. Runden Sie einfach das Floating-pt-Ergebnis auf. Wenn Sie eine genaue Anzahl von Frames benötigen, müssen Sie die Datei direkt untersuchen. Aufgrund der Besonderheiten des Video-Codecs kann es sein, dass Ihre Schätzung um ein oder zwei Punkte in beide Richtungen abweicht.
Quack Quijote
Sind dies All-in-One-File-VOBs oder DVD-VOBs, die in mehrere Dateien aufgeteilt sind?
Quack Quijote

Antworten:

17

Das ist schrecklich und dumm und langsam, scheint aber zu funktionieren:

ffmpeg -i foo.avi -vcodec copy -f rawvideo -y /dev/null 2>&1 | tr ^M '\n' | awk '/^frame=/ {print $2}'|tail -n 1

Es funktioniert auch direkt bei abgeschnittenen Dateien und RAW-Streams (daher erhalten Sie für VOB-Dateien nichts).

user23307
quelle
Das ist sehr gut. Nach meiner Erfahrung dauert es nicht so lange. Die Ausführung einer 40-minütigen Datei dauert jedoch <3 Sekunden. Denken Sie daran, dass das "^ M" nicht die 2 Zeichen ^ und M sind, Sie müssen Strg-V drücken und dann eingeben. Anstelle Ihres Befehls habe ich Folgendes verwendet: ffmpeg -i somefile.avi -vcodec copy -f rawvideo -y / dev / null 2> & 1 | tr "^ M" '\ n' | grep '^ frame =' | perl -pe 's / ^ frame = \ s * ([0-9] +) \ s. * $ / \ 1 /' | tail -n 1 Ihr Befehl schlägt fehl, wenn nach "frames =" kein Leerzeichen steht
Rory
1
In Ubuntu 12.04, ffmpeg-Version git-2013-04-15-a4f03f0, können Sie beide | tr ^M '\n'und weglassen |tail -n 1. Auch kein Leerzeichen danach frames=scheitert nicht. (Vielleicht hat sich in den letzten vier Jahren etwas geändert.)
Camille Goudeseune
für mich ergeben sich jedes mal andere
werte
1
Mediainfo-Lösung funktioniert mit VOB .. Ich würde das stattdessen empfehlen. root @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count Bildanzahl: 175715
Bildanzahl
32

ffprobe kann verwendet werden, um Informationen zu einer Mediendatei abzurufen:

ffprobe -select_streams v -show_streams input.avi

Sie erhalten Details zum Stream:

nb_frames=159697

Suchen Sie nb_framesmit grep:

ffprobe -select_streams v -show_streams input.avi 2>/dev/null | grep nb_frames | sed -e 's/nb_frames=//'

Das funktioniert für avi, mp4 und etc. Bei einigen Containern wird kein gültiger Wert angezeigt, z. B. mpeg.

In diesem Fall funktioniert dies ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l

Nachbeben
quelle
Gute Idee. Ich habe den Befehl ein wenig geändert, sodass nur der Videostream ausgewählt und die Ausgabe gefiltert wird. Das gibt Ihnen nur die Anzahl der Frames.
Slhck
1
Herzlichen Glückwunsch zu Ihrer 2. Lösung, die mit MPEG-2 funktioniert!
Malat
1
Es funktioniert nicht mit MKV-Containern.
Cenk Alti
1
nb_frames = N / A für diese Datei: web.archive.org/web/20180117220713/http://techslides.com/demos/…
Ciro Santilli am
Es scheint, dass der erste Ansatz für VBR-codierte Dateien fehlschlägt. Der zweite Ansatz ist zuverlässiger.
Elder Geek
16

Ich habe dies auf einer anderen Frage gepostet . Mit dem tcprobeTool (aus dem transcodePaket) ist die Anzahl der Frames in der Info enthalten. Verwenden Sie den -iSchalter, um einen Info-Dump aus der Datei abzurufen:

$ tcprobe -i foo.avi
[tcprobe] RIFF data, AVI video
[avilib] V: 29.970 fps, codec=XVID, frames=38630, width=512, height=384
[avilib] A: 48000 Hz, format=0x55, bits=16, channels=2, bitrate=128 kbps,
[avilib]    53707 chunks, 21768720 bytes, VBR
[tcprobe] summary for foo.avi, (*) = not default, 0 = not detected
import frame size: -g 512x384 [720x576] (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
      audio track: -a 0 [0] -e 48000,16,2 [48000,16,2] -n 0x55 [0x2000] (*)
                   bitrate=128 kbps
           length: 38630 frames, frame_time=33 msec, duration=0:21:28.954

Beachten Sie, dass die Anzahl der Frames hier in zwei Zeilen angegeben ist (2. Ausgabezeile und letzte Ausgabezeile).

Quacksalber
quelle
Das sieht nach einer guten Antwort aus und funktioniert für einige Dateien, aber für einige VOB-Dateien, die ich habe, habe ich diese Daten nicht in der Ausgabe. Ich habe die Frage mit der Ausgabe aktualisiert, die ich erhalte
Rory
Ich gehe davon aus (weiß aber nicht genau), dass tcprobe die Datei-Header auf diese Informationen überprüft. Wenn es nicht im Header enthalten ist, versucht tcprobe möglicherweise nicht, es zu berechnen. gute Frage; Ich wünschte, ich hätte eine gute Antwort für dich.
Quack Quijote
Dies scheint bei VBR-codierten Dateien nicht zu funktionieren. Ich erhalte keine Ausgabe der Bildanzahl. Ich bekomme Auflösung, Seitenverhältnis und Bildrate.
Elder Geek
7

Ich habe festgestellt, dass das mediainfo --fullscan inputfile | grep "Frame count"für die meisten Dateien gut funktioniert.

Debian-basierte Systeme können es mit installieren apt-get install mediainfo

Wenn Sie 2 Zeilen anstatt einer Ausgabe erhalten, ist die erste Zeile die Videospur und die zweite Zeile die Audiospur. Dies scheint bei Dateien mit variabler Bitrate der Fall zu sein.

Getestet auf .mkv-, .m4v-, .mp4-, flv-, vob- und .avi-Samples zum Zeitpunkt der Bearbeitung.

Quellen: Wie kann man unter Linux Informationen zu Videodateien von der Kommandozeile abrufen? und Testen unter Ubuntu-Aromen.

Hier finden Sie mediainfo für Ihr Betriebssystem .

Elder Geek
quelle
4

ffprobe -select_streams v -show_frames -count_frames INPUT_FILE | grep pkt_duration_time =

Addieren Sie die Dauer. Könnte mit sed / awk schicker sein und was nicht.

Aus unseren Tests kann ich sagen, dass es sich vorerst als das zuverlässigste erwiesen hat. Sie erhalten eine genaue Framecount und genaue Dauer. Selbst mit variabler Framerate scheinen alle anderen Tools wie mediainfo gaga zu werden.

Guillaume Blain
quelle
3

Ich habe festgestellt, dass die Anzahl der Frames tatsächlich doppelt so groß ist wie die fps * -Dauer (keine Ahnung warum, ich würde es gerne wissen).

In einem Skript von mir habe ich:

# Get duration and fps
duration=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Duration: \([^,]*\), start: .*/\1/p")
fps=$($FFMPEG -i $input 2>&1 | sed -n "s/.*, \(.*\) tb.*/\1/p")

hours=$(echo $duration | cut -d":" -f1)
minutes=$(echo $duration | cut -d":" -f2)
seconds=$(echo $duration | cut -d":" -f3)
# For some reason, we have to multiply by two (no idea why...)
# Get the integer part with cut
frames=$(echo "($hours*3600+$minutes*60+$seconds)*$fps*2" | bc | cut -d"." -f1)

Und ja, aus irgendeinem Grund muss ich den ganzzahligen Teil davon bekommen. Es macht keinen Sinn, aber dieses Skript hat es bisher immer geschafft, meine Videos richtig zu konvertieren.

ℝaphink
quelle
Denn FPS steht für Frames Per Second (oder Ego-Shooter: D) und wenn es 30 FPS gibt, multiplizieren Sie es einfach mit der Anzahl der Sekunden im Video.
John T
Ja, John, ich könnte das herausfinden, aber das erklärt nicht, warum ich es mit 2 multiplizieren muss, um die richtige Anzahl von Frames zu erhalten ... Nachdem ich die Anzahl von Frames berechnet hatte, startete ich ffmpeg im Hintergrund und analysierte die Protokolle, um einen Fortschrittsbalken zu machen. In den Protokollen wird angezeigt, wie viele Frames bei der Konvertierung übergeben wurden. Sobald das gesamte Video konvertiert wurde, war das Bild # int (Sekunden * fps * 2), daher mein Code, aber ich würde gerne wissen, warum ;-)
ℝaphink
das ist neugierig; Die tcprobeAusgabe in meiner Antwort gibt die Anzahl der Frames in Sekunden * fps (aufgerundet) an. Ich gehe davon aus, dass Sie eine Eigenart von ffmpeg sehen. Haben Sie versucht, die Datei mit anderen Tools zu analysieren, um festzustellen, ob sie die gleiche Anzahl von Frames enthält?
Quacksalber 17.
Hmmm ... Interessant. Ich habe ein Video anprobiert und bekam seconds*fps=1001.59und tcprobe=1002. Also, tcprobesagt mir, dass ich nicht mit zwei multiplizieren muss. Warum gibt mir ffmpeg dann eine doppelt so große Zahl in den Protokollen, wenn es konvertiert?
ℝaphink
2
ist es interlaced footage? Wenn ja, gibt es zwei Felder pro Frame, und es könnte Ihnen die Anzahl der Felder geben.
Stib
3

Getestet auf Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- melt war als Testwerkzeug für das MLT-Framework gedacht, ist aber auch ein leistungsfähiger, auf mehrere Spuren basierender, befehlszeilenorientierter Videoeditor. Es kann auch als minimalistischer Mediaplayer für Audio- und Videodateien verwendet werden.

  • -consumerid [: arg] [name = value] *
    Setzt den Consumer (sink)

  • xml - Setzen Sie den Consumer (Senke) auf eine XML-formatierte Ausgabe

  • <property name="length">nnnn</property>- Zeigt die Anzahl der Frames an, wobei diese nnnndurch eine Ganzzahl ersetzt wird, die der Anzahl der Frames entspricht

Wenn Sie kein Melt haben, können Sie es auf Ubuntu und anderen Debian-basierten Systemen mit installieren sudo apt-get install melt

neoneye
quelle
1
Dies ist sehr kurz. Möchten Sie näher erläutern, warum es funktioniert usw.?
David
Dies funktioniert gut bei h264 mp4-Dateien, bei denen der Framecount nicht über bereitgestellt wird mediainfo -fullscan filename.
Elder Geek
3

Direkt mit mediainfo, kein Grep, kein Warten, kein Nichts:

mediainfo --Inform='Video;%FrameCount%' $the_file

Weitere Informationen finden Sie unter mediainfo --info-parameters

Magnet
quelle
0

Sie können dies tun, indem Sie die Werte, die Sie von ffprobe erhalten, addieren und multiplizieren.

Hinweis: ffprobe ist Teil von libav (avconv) - der Linux-Version von ffmpeg.

#your command -
 ffprobe man.avi

Wenn Sie dies tun, erhalten Sie die Anzahl der Bilder pro Sekunde und auch die Dauer des Clips.

Konvertieren Sie die Dauer des Clips in Sekunden und multiplizieren Sie diesen Wert mit der Anzahl der Bilder / Sekunde.

Denken Sie daran, die Zahl auf die nächste aufzurunden.

JJAtairu
quelle
Auf Ubuntu 14.04 LTS ffprobeist nicht verfügbar, aber es ist etwas , genannt avprobein libav-tools(was bietet auch avconv). Aber an meiner Seite werden keine Frames gedruckt, zumindest nicht für die Formate, die ich ausprobiert habe. Es wird nur gedruckt, was auch avprobe -igedruckt wird, und das sind leider nur ein paar Kleinigkeiten über das Format. Auch -v debugwenn es mir nur ein paar nette Eigenschaften meiner installierten Hardware und Software verrät, gibt es keine interessanten Informationen über die zu prüfende Datei / den Stream. Vielleicht verbirgt es sich in einigen der unzähligen verfügbaren Optionen. Wer weiß?
Tino
@Tino ffprobe ist in der Tat als Teil des ffmpeg-Pakets verfügbar. avconv ist eine Gabelung von ffmpeg und hat einige Verwirrung gestiftet. Siehe: stackoverflow.com/questions/9477115/…
Elder Geek
@ElderGeek Für Ubuntu 14.04 LTS gibt es keine ffmpegin den offiziellen Repositories. Der Link, den Sie korrekt angegeben haben, besagt, dass FFmpeg in Ubuntu 15.04 "Vivid Vervet" zurückgegeben wurde. . Die Situation hat sich jedoch geändert, da 16.04 LTS aus ist.
Tino
@Tino Das ist in der Tat eine Tatsache. Allerdings würde ich nicht mit nicht verfügbar gleichsetzen, existiert nicht in den Repositories. Sie werden feststellen, dass es für Trusty (14.04) hier erhältlich ist: ffmpeg.org/download.html
Elder Geek
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 Maluk
quelle
-2

Beste Methode: (Direkt durch Berechnung der richtigen Parameter, bestätigt durch ffmpeg)

Befehl ->

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"

Ergebnis ->

r_frame_rate=24000/1001
duration=8177.794625

Berechnung ->

Frames=24000/1001*8177.794625=196071 (exactly... ;P)

Beweis ->

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

Hier

frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x

Ausgabe

video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
shareeditdeleteflag
Gerard Wensink
quelle
Ich erhalte r_frame_rate = 25/1 duration = N / A
Elder Geek