Recupera il numero di frame con ffmpeg


Risposte:


158

Nota: la presenza di un elenco di modifiche in MP4 / M4V / M4A / MOV può influire sul numero di fotogramma. Vedere Modifica elenchi di seguito.


ffprobe: interroga il contenitore

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Questo è un metodo veloce.
  • Non tutti i formati (come Matroska) riporteranno il numero di frame risultanti nell'output di N/A. Vedere gli altri metodi elencati di seguito.

ffprobe: conta il numero di frame

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Questo è un metodo lento.
  • Aggiungi l' -skip_frame nokeyopzione per contare solo i fotogrammi chiave.

ffmpeg: conta il numero di frame

Se non lo ffprobehai puoi usare ffmpeginvece:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Questo è un metodo piuttosto veloce.
  • Fare riferimento a frame=quasi la fine dell'output della console.
  • Aggiungi l' -discard nokeyopzione di input (prima -i) per contare solo i fotogrammi chiave.

Modifica elenchi

Ignora l'elenco di modifica MP4 / M4V / M4A / MOV con l' -ignore_editlist 1opzione di input. L'impostazione predefinita è di non ignorare l'elenco di modifiche.

Cosa significano le opzioni ffprobe

  • -v error Questo nasconde l'output di "info" (informazioni sulla versione, ecc.) Che rende più facile l'analisi.

  • -count_frames Contare il numero di frame per stream e segnalarlo nella sezione stream corrispondente.

  • -select_streams v:0 Seleziona solo il flusso video.

  • -show_entries stream=nb_frameso -show_entries stream=nb_read_framesMostra solo la voce per nb_frameso nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Imposta il formato di output (noto anche come "scrittore") su default, non stampare la chiave di ogni campo ( nokey=1) e non stampare l'intestazione e il piè di pagina della sezione ( noprint_wrappers=1). Esistono alternative più brevi come -of csv=p=0.

Vedi anche


MediaInfo

Il noto mediainfostrumento può produrre il numero di frame:

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

MP4Box

Per file MP4 / M4V / M4A.

MP4Box da gpac può mostrare il numero di frame:

MP4Box -info input.mp4

Fare riferimento alla Media Inforiga nell'output per il flusso video in questione:

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

In questo esempio il flusso video ha 2525 fotogrammi.


boxdumper

Per file MP4 / M4V / M4A / MOV.

boxdumperè un semplice strumento di l-smash. Produrrà una grande quantità di informazioni. Nella stszsezione della casella delle dimensioni del campione, fare riferimento a sample_countper il numero di frame. In questo esempio l'ingresso ha 1900 frame video:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Tieni presente che un file può contenere più di un stszatomo.

5
Oppure, se vuoi più velocità e se nb_frames è abbastanza affidabile, semplifica come ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
segue

Questo restituisce la risposta due volte per me (cioè 2600 \ n 2600). Qualche motivo particolare che potrebbe accadere?
jbodily

@jbodily Il mio esempio o quello di juanitogan? Non posso duplicarlo neanche usando. Non c'è molto con cui lavorare qui.
llogan

+1, non da ultimo perché, a differenza di troppe altre risposte su qualsiasi strumento da riga di comando, questa in realtà spiega tutte le opzioni della riga di comando. Grazie.
Ray

1
Si noti che la prima opzione, interrogare il contenitore, elabora effettivamente il file a causa di count_frames. Vedi il commento di @ juanitogan.
aggieNick02

24

In Unix, funziona come un fascino:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '

3
Davvero una bella. Semplicemente non è necessario copiare il flusso audio. Puoi usare -an instat.
rekire

1
@PrakharMohanSrivastava Controlla questa risposta
Antonio

4
In realtà, questo sembra veloce e affidabile: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 grazie per il sorriso con il mio caffè mattutino :-)
Lloyd Moore

1
@TimothyZorn Hai reso la mia giornata!
Mladen Danic

13

Calcolalo in base al tempo, invece.

Questo è quello che faccio e funziona alla grande per me e per molti altri.) Innanzitutto, trova la lunghezza del video nello snippet seguente:

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

Dovresti essere in grado di trovare in modo coerente e sicuro Duration: hh:mm:ss.nnper determinare la dimensione del video clip di origine. Quindi, per ogni riga di aggiornamento (CR, no LF) puoi analizzare il testo per l'indicatore di tempo corrente in cui si trova:

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    

Basta fare attenzione a non aspettarsi sempre un risultato perfetto da queste righe di stato. Possono includere messaggi di errore come qui:

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    

Una volta che si ha il tempo, è semplice matematica: time / durration * 100 = % done.


1
Scusa se sono stupido ma come posso fare il tempo / durata quando la durata è in formato hh: mm: ss.nn e l'ora è sempre in formato xx.yy?
Omar Ali

2
@Omar, come sviluppatore .NET, quello che faccio è creare un file TimeSpanda esso, quindi utilizzare currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). Il TimeSpan fornisce anche una potente funzione Parse, dai un'occhiata
Shimmy Weitzhandler

ottima soluzione, il mio tempo è in hh: mm: ss: ms quindi suppongo che in questi 3 anni FFMPEG abbia migliorato il formato dell'ora di output.
ElektroStudios

1
Si noti che l'output della console potrebbe indicare 29,97, ma è l'abbreviazione di 30000/1001. Lo stesso per 23.98 che è 24000/1001 e 59.94 è 60000/1001.
llogan

Come nota, questo non funziona per i video con framerate variabile (ovviamente).
Timothy Zorn

8

Non tutti i formati memorizzano il numero di fotogrammi o la durata totale e, anche se lo fanno, il file potrebbe essere incompleto, quindi ffmpeg non rileva nessuno dei due in modo accurato per impostazione predefinita.

Invece, prova a cercare fino alla fine del file e leggi l'ora, quindi conta l'ora corrente mentre vai.

In alternativa, puoi provare AVFormatContext->nb_index_entrieso la durata rilevata, che dovrebbe funzionare bene su AVI / MOV almeno non danneggiati, o la libreria FFMS2, che probabilmente è troppo lenta per una barra di avanzamento.


8

Prova qualcosa come:

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

Scrive il numero di frame su stderr, quindi puoi recuperare l'ultimo frame da questo.


8

È possibile utilizzare ffprobe per ottenere il numero di frame con i seguenti comandi

  1. primo metodo

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

che dicono di stampare i dati in jsonformato

select_streams vdirà ffprobedi fornirci solo i dati di videostreaming e se lo rimuovi, fornirà anche audioinformazioni

e l'output sarà come

{
    "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. puoi usare

ffprobe -v error -show_format -show_streams video_name

che ti darà i dati di streaming, se desideri informazioni selezionate come la frequenza dei fotogrammi, usa il seguente comando

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

che fornisce una base numerica sulle informazioni video, il problema è che quando si utilizza questo metodo, è possibile che si ottenga un N/Aoutput.

per maggiori informazioni controlla questa pagina FFProbe Tips


4

prova questo:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '

Non funziona con *.ts. L'output è una riga vuota.
Victor Polevoy

3

Dato che il mio commento ha ricevuto alcuni voti positivi, ho pensato di lasciarlo come risposta:

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

Dovrebbe essere veloce, poiché non viene eseguita alcuna codifica. ffmpegeseguirà il demux del file e leggerà (decodificherà) il primo flusso video il più rapidamente possibile. Il primo grepcomando prenderà il testo che mostra la cornice. Il secondo grepcomando prenderà solo il numero da quello. Il tailcomando mostrerà solo la riga finale (conteggio frame finale).


2

per costruire sulla risposta di stu. ecco come ho trovato il frame rate per un video dal mio telefono cellulare. ho eseguito il seguente comando per un po '. ho lasciato che il conteggio dei frame arrivasse a circa ~ 10.000 prima di diventare impaziente e premere ^ C:

$ 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.
$

poi, ho preso due informazioni da quella riga che inizia con "frame =", il conteggio dei frame, 7989 e l'ora, 00: 04: 26.30. Devi prima convertire il tempo in secondi e poi dividere il numero di fotogrammi per secondi per ottenere "fotogrammi al secondo". "fotogrammi al secondo" è il tuo frame rate.

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

7989/(4*60+26.3)
30.00000000000000000000
$

il framerate per il mio video è di 30 fps.


2

L'unico modo accurato che sono riuscito a fare è il seguente:

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

Per assicurarti che funzioni con il video:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video

Ho votato positivamente la tua risposta, ma funzionerà solo se il video non contiene audio. Se contiene, questo funzionerà:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe

2

Ci scusiamo per la risposta negativa, ma forse ne avrò bisogno (dato che non ho trovato una soluzione per le recenti versioni di ffmpeg.

Con ffmpeg 3.3.4 ho trovato che si può trovare con quanto segue:

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

Alla fine emetterà il conteggio dei frame. Ha funzionato per me sui video con audio. Tuttavia, fornisce due volte una riga "nb_frames", ma la prima riga era il conteggio effettivo dei fotogrammi nei video che ho testato.


Grazie @ acidrums4. Verificato che questo metodo funzioni con l'ultima versione di GitHub che ho creato oggi.
Paul J

1

Uso il php_ffmpeg quindi posso ottenere tutti i tempi e tutti i fotogrammi di un film. Come belows

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

E poi il dettaglio è sulla pagina.

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


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

La frequenza fotogrammi viene normalmente calcolata su due parametri. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Arrotondato da ffmpeg a: 23,98 Durata = ore * 3600 + minuti * 60 + secondi. restante = 8177,91 Pur parametro durata = 8177.794625 Ma Frames = 24000/1001 * 8177.794625 = 196071 fornisce il numero esatto di frame. (Non sto scherzando).
Gerard Wensink

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