Come posso ottenere il numero di frame in un video dalla riga di comando di Linux?


30

Ho un file video e voglio ottenere il numero di fotogrammi video presenti. Posso usare ffmpegper ottenere la lunghezza del video e l'FPS. Tuttavia non vedo nulla di ovvio per il numero totale di frame.

In teoria si dovrebbe essere in grado di moltiplicare la lunghezza (in secondi) per l'FPS per ottenere il numero di frame, ma in questo caso la lunghezza (34,43 secondi) e il framerate (29,97 fps) danno un non intero, il che mi rende penso che sto facendo qualcosa di sbagliato.

Devo essere in grado di farlo sulla riga di comando in modo totalmente automatizzato e non grafico. Ho anche bisogno che questo sia abbastanza esatto e non una stima (se ciò è possibile anche con i file video)

Ho provato ad usare tcprobealcuni file. Per alcuni file AVI funziona, ma per alcuni file VOB, l'output di tcprobe non ha il numero di frame. Ottengo questo risultato:

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

la tua equazione ti darà una buona stima del ballpark; appena intorno al risultato in virgola mobile verso l'alto. se hai bisogno di un numero esatto di fotogrammi dovrai esaminare direttamente il file - la tua stima potrebbe essere disattivata di uno o due in entrambe le direzioni a causa dei dettagli del codec video.
Quack Quixote,

sono VOB all-in-one-file o VOB suddivisi in file multipli in stile DVD?
Quack Quixote,

Risposte:


17

Questo è orribile, stupido e lento, ma sembra funzionare:

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

Funzionerà anche su file troncati e flussi non elaborati (ecco perché non ottieni nulla per i file .vob)


È piuttosto buono. Nella mia esperienza, non ci vuole molto tempo. L'esecuzione di un file di 40 minuti richiede circa <3 secondi. Ricorda che "^ M" non è composto da 2 caratteri ^ e M, devi premere Control-V e quindi accedere. Invece del tuo comando ho usato: ffmpeg -i somefile.avi -vcodec copia -f rawvideo -y / dev / null 2> & 1 | tr "^ M" '\ n' | grep '^ frame =' | perl -pe 's / ^ frame = \ s * ([0-9] +) \ s. * $ / \ 1 /' | tail -n 1 Il tuo comando fallisce se non c'è spazio dopo "frames ="
Rory

1
In Ubuntu 12.04, versione ffmpeg git-2013-04-15-a4f03f0, è possibile omettere sia | tr ^M '\n'e |tail -n 1. Inoltre, nessuno spazio dopo frames=non fallisce. (Forse qualcosa è cambiato negli ultimi quattro anni.)
Camille Goudeseune,

per me questo ritorno ogni volta valori diversi
CAMOBAP

1
La soluzione Mediainfo funziona con VOB .. Lo consiglierei invece. root @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count Numero di frame: 175715 Numero di frame: 183218
kevinf

32

ffprobe può essere utilizzato per ottenere informazioni su un file multimediale:

ffprobe -select_streams v -show_streams input.avi

Otterrai dettagli sullo stream:

nb_frames=159697

Cerca nb_framescon grep:

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

Funziona con avi, mp4 ed ecc. Per alcuni container, non mostra un valore valido, ad es. Mpeg.

In tal caso, funziona ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l


Buona idea. Ho modificato un po 'il comando in modo da selezionare solo il flusso video e filtrare l'output. Questo ti dà solo il numero di frame.
slhck,

1
Complimenti per la tua seconda soluzione che funziona con MPEG-2!
malat,

1
Non funziona con i contenitori MKV.
Cenk Alti,


Sembra che il primo approccio fallisca sui file codificati VBR. Il secondo approccio è più affidabile.
Elder Geek

16

Ho pubblicato questo su un'altra domanda . Utilizzando lo tcprobestrumento (dal transcodepacchetto), il numero di frame è incluso nelle informazioni. Utilizzare l' -iopzione per ottenere un dump di informazioni dal file:

$ 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

Notare che qui è indicato il numero di frame su due righe (seconda riga di output e ultima riga di output).


Sembra una buona risposta, e funziona per alcuni file, ma per alcuni file VOB che ho, non ho quei dati nell'output. Ho aggiornato la domanda con l'output che ottengo
Rory il

mi aspetto (ma non lo so per certo) che tcprobe sta esaminando le intestazioni dei file per queste informazioni. se non è incluso nell'intestazione, tcprobe potrebbe non tentare un calcolo per esso. buona domanda; vorrei avere una buona risposta per te.
Quack Quixote

Questo non sembra funzionare su file codificati VBR. Non ottengo alcun output di conteggio dei frame. Ottengo risoluzione, proporzioni e frame rate.
Elder Geek

7

Ho scoperto che mediainfo --fullscan inputfile | grep "Frame count"funziona bene per la maggior parte dei file.

I sistemi basati su Debian possono installarlo con apt-get install mediainfo

Se ottieni 2 righe anziché una di output, la prima riga è la traccia video e la seconda riga è la traccia audio. Sembra che ciò si verifichi su file con audio a velocità in bit variabile.

Testato su campioni .mkv, .m4v, .mp4, flv, vob e .avi alla data di modifica.

Fonti: Come recuperare le informazioni sui file video dalla riga di comando in Linux? e test con gusti Ubuntu.

Puoi trovare mediainfo disponibile per il tuo sistema operativo qui.


4

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

Aggiungi la durata. Potrebbe essere più elaborato con sed / awk e cosa no.

Dai nostri test posso dire che per ora ha dimostrato di essere il migliore più affidabile. Ottieni un framecount preciso e una durata esatta. Anche con framerate variabile che tutti gli altri strumenti come mediainfo sembrano diventare gaga.


3

Ho scoperto che il numero di fotogrammi è in realtà il doppio della durata di fps * (non ho idea del perché, sarei felice di saperlo).

In una mia sceneggiatura ho:

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

E sì, per qualche motivo devo ottenerne la parte intera. Non ha senso, ma questo script è sempre riuscito a convertire correttamente i miei video finora.


Perché FPS sta per Frames Per Second (o sparatutto in prima persona: D) e se ci sono 30 FPS semplicemente moltiplicalo per quanti secondi ci sono nel video.
John T,

Sì John, ho potuto capirlo, ma ciò non spiega perché devo moltiplicarlo per 2 per ottenere la giusta quantità di frame ... Nel mio caso, dopo aver calcolato la quantità di frame, ho lanciato ffmpeg nel sfondo e analizzato i log per creare una barra di avanzamento. I registri mostrano quanti frame sono passati nella conversione. Una volta convertito l'intero video, il frame # era int (secondi * fps * 2), quindi il mio codice, ma mi piacerebbe sapere perché ;-)
ℝaphink,

è curioso; l' tcprobeoutput nella mia risposta fornisce il numero di frame esattamente come secondi * fps (arrotondato per eccesso). mi aspetto che tu stia vedendo una stranezza di ffmpeg. hai provato ad analizzare il file con altri strumenti per vedere se mostrano lo stesso numero di frame?
Quack Quixote il

Hmmm ... Interessante. Ho provato un video e ho ottenuto seconds*fps=1001.59e tcprobe=1002. Quindi, ovviamente, tcprobemi dice che non ho bisogno di moltiplicare per due. Perché allora ffmpeg mi dà un numero che è due volte più grande nei registri durante la conversione?
inkaphink,

2
sono filmati interlacciati? In tal caso, ci sono due campi per frame e potrebbe darti il ​​numero di campi.
Stib

3

Testato su Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- melt era inteso come strumento di test per il framework MLT, ma è anche un potente editor video orientato alla riga di comando multitraccia. Potrebbe anche essere usato come un lettore multimediale minimalista per file audio e video.

  • -consumerid [: arg] [nome = valore] *
    Imposta il consumatore (sink)

  • xml - Impostare il consumatore (sink) su output formattato xml

  • <property name="length">nnnn</property>- mostra il numero di frame, dove nnnnviene sostituito da un numero intero che è uguale al numero di frame

Se non hai il melt puoi installarlo su Ubuntu e altri sistemi basati su Debian con sudo apt-get install melt


1
Questo è molto breve, vuoi espandere ciò che fa, perché funziona, ecc.?
David,

Funziona bene su file mp4 h264 che non forniscono il framecount tramite mediainfo -fullscan filename.
Elder Geek,

3

Direttamente con mediainfo, no grep, no wait, no nothing:

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

Per altre informazioni vedi mediainfo --info-parameters


0

Puoi farlo aggiungendo e moltiplicando i valori che ottieni da ffprobe.

Nota: ffprobe fa parte di libav (avconv) - la versione linux di ffmpeg.

#your command -
 ffprobe man.avi

In questo modo otterrai il numero di fotogrammi al secondo e anche la durata della clip.

Converti la durata della clip in secondi e moltiplica quel valore per il numero di fotogrammi / secondo.

Ricorda di arrotondare il numero al più vicino.


Su Ubuntu 14.04 LTS ffprobenon è disponibile, ma c'è qualcosa chiamato avprobein libav-tools(che fornisce anche avconv). Ma al mio fianco non stampa alcun numero di fotogrammi, almeno non per i formati che ho provato. Stampa, anche ciò che avprobe -istampa, e questo è solo alcuni piccoli dettagli sul formato, purtroppo. Anche con -v debugquesto mi dice solo alcune belle proprietà del mio hardware e software installato, ma non un po 'di informazioni interessanti sul file / flusso da sondare. Forse si nasconde in alcune delle miriadi di opzioni disponibili. Chissà?
Tino,

@Tino ffprobe è effettivamente disponibile come parte del pacchetto ffmpeg. avconv è un fork di ffmpeg e ha creato confusione. Vedi: stackoverflow.com/questions/9477115/…
Elder Geek,

@ElderGeek Per Ubuntu 14.04 LTS non c'è ffmpegnei repository ufficiali. Il link che hai fornito lo afferma correttamente: FFmpeg restituito in Ubuntu 15.04 "Vivid Vervet". . Tuttavia, la situazione ora è cambiata quando 16.04 LTS è fuori.
Tino,

@Tino Questo è davvero un dato di fatto. Tuttavia non identificherei non disponibile con non esiste nei repository. Noterai che è disponibile per Trusty (14.04) qui: ffmpeg.org/download.html
Elder Geek,

0

linux

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

rubino

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

-2

Metodo migliore: (diretto calcolando i parametri giusti, confermato da 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"

Risultato ->

r_frame_rate=24000/1001
duration=8177.794625

Calcolo ->

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

Prova ->

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

Qui

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

Produzione

video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
shareeditdeleteflag

Ottengo r_frame_rate = 25/1 durata = N / A
Elder Geek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.