Jak uzyskać liczbę klatek w filmie w wierszu poleceń systemu Linux?

30

Mam plik wideo i chcę uzyskać liczbę klatek wideo, które się w nim znajdują. Mogę użyć, ffmpegaby uzyskać długość filmu i FPS. Jednak nie widzę nic oczywistego dla całkowitej liczby ramek.

Teoretycznie należy mieć możliwość pomnożenia długości (w sekundach) przez liczbę klatek na sekundę, aby uzyskać liczbę klatek, ale w tym przypadku długość (34,43 sekundy) i liczba klatek na sekundę (29,97 kl./s) dają liczbę całkowitą, co czyni mnie myślę, że robię coś złego.

Muszę być w stanie to zrobić w wierszu poleceń w całkowicie zautomatyzowany i nie graficzny sposób. Potrzebuję również, aby było to dość dokładne, a nie szacunkowe (jeśli jest to nawet możliwe w przypadku plików wideo)

Próbowałem użyć tcprobeniektórych plików. W przypadku niektórych plików AVI to działa, ale w przypadku niektórych plików VOB wyjście tcprobe nie ma liczby ramek. Otrzymuję ten wynik:

[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
źródło
twoje równanie da ci dobre oszacowanie ballpark; wystarczy zaokrąglić wynik zmiennoprzecinkowy w górę. jeśli potrzebujesz dokładnej liczby klatek, musisz zbadać plik bezpośrednio - twoje oszacowanie może być wyłączone o jeden lub dwa w obu kierunkach ze względu na specyfikę kodeka wideo.
quack quixote
czy te VOB typu „wszystko w jednym pliku” czy VOB typu „podzielone na wiele plików” w stylu DVD?
quix quixote
1
stackoverflow.com/questions/2017843/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:

17

To jest okropne, głupie i powolne, ale wydaje się działać:

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

Działa również bezpośrednio na obcięte pliki i surowe strumienie (dlatego nic nie dostajesz dla plików .vob)

użytkownik23307
źródło
To całkiem nieźle. Z mojego doświadczenia wynika, że ​​nie trwa to długo. Uruchomienie pliku trwającego 40 minut zajmuje jednak mniej niż 3 sekundy. Pamiętaj, że „^ M” to nie 2 znaki ^ i M, musisz nacisnąć Control-V, a następnie wprowadzić. Zamiast polecenia użyłem: 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 Twoje polecenie kończy się niepowodzeniem, jeśli po „frames =” nie ma spacji
Rory
1
W Ubuntu 12.04, wersja ffmpeg git-2013-04-15-a4f03f0, możesz pominąć zarówno | tr ^M '\n'i |tail -n 1. Ponadto, żadne spacja po frames=nie zawiedzie. (Może coś się zmieniło w ciągu ostatnich czterech lat.)
Camille Goudeseune,
dla mnie ten zwrot za każdym razem inne wartości
CAMOBAP
1
Rozwiązanie Mediainfo współpracuje z VOB .. Polecam to zamiast tego. root @ lanparty: / mnt / movies # mediainfo --fullscan Bugs_Bunny.vob | grep -i ramka \ liczba Liczba klatek: 175715 Liczba klatek: 183218
kevinf
32

ffprobe można użyć do uzyskania informacji o pliku multimedialnym:

ffprobe -select_streams v -show_streams input.avi

Otrzymasz szczegółowe informacje o strumieniu:

nb_frames=159697

Poszukaj za nb_framespomocą grep:

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

Działa to dla avi, mp4 itp. W przypadku niektórych kontenerów nie wyświetla prawidłowej wartości, np. Mpeg.

W takim przypadku to działa ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l

Po szoku
źródło
Dobry pomysł. Zmodyfikowałem nieco to polecenie, tak aby wybierało tylko strumień wideo i filtrowało dane wyjściowe. To daje tylko liczbę klatek.
slhck
1
Gratulujemy drugiego rozwiązania, które współpracuje z MPEG-2!
Malat
1
Nie działa z pojemnikami MKV.
Cenk Alti
1
nb_frames = Nie dotyczy tego pliku: web.archive.org/web/20180117220713/http://techslides.com/demos/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Wydaje się, że pierwsze podejście kończy się niepowodzeniem na plikach zakodowanych w VBR. Drugie podejście jest bardziej niezawodne.
Starszy Geek
16

Wysłałem to na inne pytanie . Za pomocą tcprobenarzędzia (z transcodepakietu) liczba ramek jest zawarta w informacji. Użyj -iprzełącznika, aby uzyskać zrzut informacji z pliku:

$ 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

Zauważ, że liczba ramek jest podana tutaj w dwóch liniach (2. linia wyjściowa i ostatnia linia wyjściowa).

quack quixote
źródło
To wygląda na dobrą odpowiedź i działa na niektóre pliki, ale w przypadku niektórych plików VOB mam te dane wyjściowe. Zaktualizowałem pytanie o otrzymany wynik
Rory,
spodziewam się (ale nie wiem na pewno), że tcprobe sprawdza nagłówki plików dla tych informacji. jeśli nie jest uwzględniony w nagłówku, tcprobe może nie podjąć próby jego obliczenia. dobre pytanie; chciałbym mieć dla ciebie dobrą odpowiedź.
quack quixote
Nie działa to na pliki zakodowane w VBR. Nie otrzymuję danych wyjściowych zliczania klatek. Dostaję rozdzielczość, współczynnik kształtu i liczbę klatek na sekundę.
Starszy Geek
7

Przekonałem się, że mediainfo --fullscan inputfile | grep "Frame count"działa ładnie dla większości plików.

Systemy oparte na Debianie mogą go zainstalować apt-get install mediainfo

Jeśli otrzymujesz 2 linie zamiast jednego wyjścia, pierwszy wiersz jest ścieżką wideo, a drugi wiersz jest ścieżką audio. Wygląda na to, że dzieje się tak w przypadku plików z dźwiękiem o zmiennej przepływności.

Testowane na próbkach .mkv, .m4v, .mp4, flv, vob i .avi na dzień edycji.

Źródła: Jak pobrać informacje o pliku wideo z wiersza poleceń w systemie Linux? i testowanie w wersjach Ubuntu.

Informacje o multimediach dostępne dla twojego systemu operacyjnego można znaleźć tutaj.

Starszy Geek
źródło
4

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

Dodaj czas trwania. Może być bardziej elegancki z sed / awk i co nie.

Z naszych testów mogę stwierdzić, że na razie okazało się, że jest najbardziej niezawodny. Otrzymasz dokładną liczbę klatek i dokładny czas trwania. Nawet przy zmiennej liczbie klatek na sekundę, którą wszystkie inne narzędzia, takie jak mediainfo, wydają się być gaga.

Guillaume Blain
źródło
3

Przekonałem się, że liczba klatek jest w rzeczywistości dwa razy dłuższa niż fps * (nie mam pojęcia dlaczego, chętnie bym wiedział).

W moim skrypcie mam:

# 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)

I tak, z jakiegoś powodu muszę uzyskać część całkowitą. To nie ma sensu, ale ten skrypt do tej pory zawsze poprawnie konwertował moje filmy.

Inkaphink
źródło
Ponieważ FPS oznacza liczbę klatek na sekundę (lub FPS: D), a jeśli jest 30 klatek na sekundę, wystarczy pomnożyć go przez liczbę sekund w filmie.
John T
Tak John, mogłem to rozgryźć, ale to nie wyjaśnia, dlaczego muszę pomnożyć to przez 2, aby uzyskać odpowiednią liczbę ramek ... W moim przypadku, po obliczeniu liczby ramek, uruchomiłem ffmpeg w tło i przeanalizował dzienniki, aby utworzyć pasek postępu. Dzienniki pokazują, ile ramek przeszło podczas konwersji. Po przekonwertowaniu całego wideo ramka # była int (sekundy * fps * 2), stąd mój kod, ale chciałbym wiedzieć, dlaczego ;-)
ℝaphink
to ciekawe; tcprobewyjście w mojej odpowiedzi daje # klatek jak dokładnie sekund * fps (w zaokrągleniu). spodziewam się, że widzisz dziwactwo ffmpeg. próbowałeś przeanalizować plik za pomocą innych narzędzi, aby zobaczyć, czy pokazują one tę samą liczbę ramek?
quack quixote
Hmmm ... Interesujące. Próbowałem na wideo i dostałem seconds*fps=1001.59i tcprobe=1002. Więc oczywiście tcprobemówi mi, że nie muszę pomnożyć przez dwa. Dlaczego więc ffmpeg podaje mi liczbę dwukrotnie większą w dziennikach podczas konwersji?
ℝaphink,
2
czy to jest materiał z przeplotem? Jeśli tak, są dwa pola na ramkę i może to oznaczać liczbę pól.
stib
3

Testowane na Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- melt miał być narzędziem testowym dla frameworka MLT, ale jest także potężnym edytorem wideo z wieloma wierszami poleceń. Może być również używany jako minimalistyczny odtwarzacz multimediów dla plików audio i wideo.

  • -consumerid [: arg] [name = wartość] *
    Ustaw konsumenta (sink)

  • xml - Ustaw konsumenta (zlew) na formatowanie xml

  • <property name="length">nnnn</property>- pokazuje liczbę ramek, gdzie nnnnjest zastąpiona liczbą całkowitą równą liczbie ramek

Jeśli nie masz stopu, możesz zainstalować go na Ubuntu i innych systemach opartych na Debianie sudo apt-get install melt

neoneye
źródło
1
To jest bardzo krótkie, czy chcesz rozwinąć to, co robi, dlaczego działa itp.?
David
Działa to dobrze na plikach MP26 h264, które nie zapewniają liczby ramek za pośrednictwem mediainfo -fullscan filename.
Starszy Geek
3

Bezpośrednio z mediainfo, bez grep, bez czekania, bez niczego:

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

Inne informacje patrz mediainfo --info-parameters

ksenoid
źródło
0

Możesz to zrobić, dodając i mnożąc wartości otrzymane z ffprobe.

Uwaga: ffprobe jest częścią libav (avconv) - linuksowej wersji ffmpeg.

#your command -
 ffprobe man.avi

Gdy to zrobisz, otrzymasz liczbę klatek na sekundę, a także czas trwania klipu.

Konwertuj czas trwania klipu na sekundy i pomnóż tę wartość przez liczbę klatek / sekundę.

Pamiętaj, aby zaokrąglić liczbę do najbliższego.

JJAtairu
źródło
Ubuntu 14.04 LTS na ffprobenie jest dostępny, ale jest coś, co nazywa avprobesię libav-tools(co zapewnia również avconv). Ale z mojej strony nie drukuje żadnej liczby ramek, przynajmniej nie dla formatów, które wypróbowałem. Po prostu drukuje, jakie avprobe -idrukuje, i to jest tylko kilka drobnych bitów na temat formatu, niestety. Mimo -v debugto mówi mi tylko kilka fajnych właściwości zainstalowanego sprzętu i oprogramowania, ale nie ma ani jednej interesującej informacji o pliku / strumieniu do sondowania. Być może ukrywa się w wielu dostępnych opcjach. Kto wie?
Tino
@Tino ffprobe jest rzeczywiście dostępny jako część pakietu ffmpeg. avconv jest rozwidleniem ffmpeg i spowodował pewne zamieszanie. Zobacz: stackoverflow.com/questions/9477115/…
Starszy Geek
@ElderGeek Dla Ubuntu 14.04 LTS nie ma ffmpegw oficjalnych repozytoriach. Link, który podałeś poprawnie, stwierdza: FFmpeg powrócił w Ubuntu 15.04 „Vivid Vervet”. . Sytuacja zmieniła się jednak po wydaniu 16.04 LTS.
Tino
@Tino To jest rzeczywiście fakt. Jednak nie utożsamiam z niedostępnością nie istnieje w repozytoriach. Zauważysz, że jest dostępny dla Trusty (14.04) tutaj: ffmpeg.org/download.html
Starszy 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]
Jarosław Maluk
źródło
-2

Najlepsza metoda: (bezpośrednio przez obliczenie odpowiednich parametrów, potwierdzone przez ffmpeg)

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"

Wynik ->

r_frame_rate=24000/1001
duration=8177.794625

Obliczanie ->

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

Dowód ->

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

Tutaj

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

Wydajność

video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
shareeditdeleteflag
Gerard Wensink
źródło
Dostaję r_frame_rate = 25/1 czas trwania = nie dotyczy
Starszy Geek