Obter contagem de frames com ffmpeg

112

Alguém sabe como buscar o número total de quadros de um arquivo de vídeo usando o ffmpeg? A saída de renderização do ffmpeg mostra o quadro atual e eu preciso da contagem de quadros para calcular o progresso em porcentagem.

Hansl
fonte
1
superuser.com/questions/84631/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respostas:

158

Nota: A presença de uma lista de edição em MP4 / M4V / M4A / MOV pode afetar o número do seu quadro. Veja Editar listas abaixo.


ffprobe: Consultar o contêiner

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Este é um método rápido.
  • Nem todos os formatos (como Matroska) reportarão o número de quadros resultando na saída de N/A. Veja os outros métodos listados abaixo.

ffprobe: conte o número de quadros

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Este é um método lento.
  • Adicione a -skip_frame nokeyopção de contar apenas os quadros-chave.

ffmpeg: conta o número de quadros

Se você não tiver, ffprobepoderá usar ffmpeg:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Este é um método um tanto rápido.
  • Consulte frame=próximo ao final da saída do console.
  • Adicione a -discard nokeyopção de entrada (antes -i) para contar apenas os quadros-chave.

Editar listas

Ignore a lista de edição MP4 / M4V / M4A / MOV com a -ignore_editlist 1opção de entrada. O padrão é não ignorar a lista de edição.

O que significam as opções ffprobe

  • -v error Isso oculta a saída de "informações" (informações da versão, etc), o que torna a análise mais fácil.

  • -count_frames Conte o número de quadros por fluxo e relate-o na seção de fluxo correspondente.

  • -select_streams v:0 Selecione apenas o fluxo de vídeo.

  • -show_entries stream=nb_framesou -show_entries stream=nb_read_framesMostra apenas a entrada para nb_framesou nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Defina o formato de saída (também conhecido como "escritor") como default, não imprima a chave de cada campo ( nokey=1) e não imprima o cabeçalho e o rodapé da seção ( noprint_wrappers=1). Existem alternativas mais curtas, como -of csv=p=0.

Veja também


mediainfo

A mediainfoferramenta bem conhecida pode gerar o número de quadros:

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

MP4Box

Para arquivos MP4 / M4V / M4A.

MP4Box do gpac pode mostrar o número de quadros:

MP4Box -info input.mp4

Consulte a Media Infolinha na saída do stream de vídeo em questão:

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

Neste exemplo, o fluxo de vídeo tem 2525 quadros.


boxdumper

Para arquivos MP4 / M4V / M4A / MOV.

boxdumperé uma ferramenta simples do l-smash. Ele produzirá uma grande quantidade de informações. Na stszseção da caixa do tamanho da amostra, consulte sample_counto número de quadros. Neste exemplo, a entrada tem 1900 quadros de vídeo:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Esteja ciente de que um arquivo pode ter mais de um stszátomo.
llogan
fonte
5
Ou, se você quiser mais velocidade e se nb_frames for confiável o suficiente, simplifique como:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
juanitogan
Isso gera a resposta duas vezes para mim (ou seja, 2600 \ n 2600). Alguma razão particular para isso estar acontecendo?
jbodily
@jbodily Meu exemplo ou do juanitogan? Também não posso duplicar usando. Não há muito para trabalhar aqui.
llogan
+1, até porque, ao contrário de muitas outras respostas sobre qualquer ferramenta de linha de comando, esta realmente explica todas as opções de linha de comando. Obrigado.
Ray
1
Observe que a primeira opção, consultar o contêiner, realmente processa o arquivo devido a count_frames. Veja o comentário de @juanitogan.
aggieNick02
23

No Unix, isso funciona como um charme:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
ataraxic
fonte
3
Realmente um bom. Só você não precisa copiar o fluxo de áudio. Você pode usar -an instat.
rekire de
1
@PrakharMohanSrivastava Verifique esta resposta
Antonio
4
Na verdade, isso parece rápido e confiável: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 obrigado pelo sorriso com meu café da manhã :-)
Lloyd Moore
1
@TimothyZorn Você fez meu dia!
Mladen Danic
13

Em vez disso, calcule com base no tempo.

Isso é o que eu faço e funciona muito bem para mim e muitos outros.) Primeiro, encontre a duração do vídeo no snippet abaixo:

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

Você deve ser capaz de encontrar de forma consistente e segura Duration: hh:mm:ss.nnpara determinar o tamanho do videoclipe de origem. Então, para cada linha de atualização (CR, sem LF), você pode analisar o texto para a marca de tempo atual em:

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    

Apenas tome cuidado para não esperar uma saída perfeita dessas linhas de status. Eles podem incluir mensagens de erro como aqui:

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    

Assim que tiver o tempo, é matemática simples: time / durration * 100 = % done.

Stu Thompson
fonte
1
Desculpe-me por ser estúpido, mas como posso fazer tempo / duração quando a duração está no formato hh: mm: ss.nn e a hora é sempre o formato xx.yy?
Omar Ali
2
@Omar, Como um desenvolvedor .NET, o que eu faço é criar um a TimeSpanpartir dele e usar currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). O TimeSpan também oferece uma poderosa função Parse, verifique
Shimmy Weitzhandler
excelente solução, meu tempo está em hh: mm: ss: ms então suponho que nestes 3 anos o FFMPEG melhorou o formato de tempo de saída.
ElektroStudios de
1
Observe que a saída do console pode ser 29,97, mas é a abreviação de 30000/1001. O mesmo para 23,98 que é 24000/1001 e 59,94 é 60000/1001.
llogan
Como uma observação, isso não funciona para vídeos com taxa de quadros variável (obviamente).
Timothy Zorn,
8

Nem todos os formatos armazenam sua contagem de quadros ou duração total - e mesmo se o fizerem, o arquivo pode estar incompleto - então o ffmpeg não detecta nenhum deles com precisão por padrão.

Em vez disso, tente procurar o final do arquivo e ler a hora, depois conte a hora atual enquanto prossegue.

Alternativamente, você pode tentar AVFormatContext->nb_index_entriesou a duração detectada, que deve funcionar bem em AVI / MOV não danificado, ou a biblioteca FFMS2, que provavelmente é muito lenta para se preocupar com uma barra de progresso.

alex estranho
fonte
8

Experimente algo como:

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

Ele grava o número do quadro em stderr, para que você possa recuperar o último quadro a partir dele.

a1kmm
fonte
8

Você pode usar ffprobe para obter o número do quadro com os seguintes comandos

  1. primeiro método

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

que dizem para imprimir dados em jsonformato

select_streams vdirá ffprobepara apenas nos fornecer videodados de fluxo e se você removê-los, ele fornecerá audioinformações também

e a saída será como

{
    "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. você pode usar

ffprobe -v error -show_format -show_streams video_name

que fornecerá dados de fluxo, se você quiser informações selecionadas como taxa de quadros, use o seguinte comando

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

que fornecem um número com base nas informações do seu vídeo, o problema é quando você usa este método, é possível obter uma N/Asaída como.

para mais informações, consulte esta página Dicas FFProbe

Hadi Rasekh
fonte
4

tente isto:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Julien
fonte
Não funciona com o *.ts. A saída é uma linha vazia.
Victor Polevoy
3

Como meu comentário teve alguns votos positivos, achei melhor deixá-lo como uma resposta:

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

Isso deve ser rápido, uma vez que nenhuma codificação está sendo executada. ffmpegirá apenas demuxar o arquivo e ler (decodificar) o primeiro stream de vídeo o mais rápido possível. O primeiro grepcomando irá capturar o texto que mostra o quadro. O segundo grepcomando pegará apenas o número daquele. O tailcomando mostrará apenas a linha final (contagem final de quadros).

Timothy Zorn
fonte
2

para construir na resposta de stu. Veja como encontrei a taxa de quadros de um vídeo do meu celular. executei o seguinte comando por um tempo. Deixei a contagem de frames chegar a cerca de 10.000 antes de ficar impaciente e bater ^ 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.
$

então, peguei duas informações dessa linha que começa com "frame =", a contagem de frames, 7989, e o tempo, 00: 04: 26,30. Você primeiro precisa converter o tempo em segundos e depois dividir o número de quadros por segundos para obter "quadros por segundo". "quadros por segundo" é a sua taxa de quadros.

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

7989/(4*60+26.3)
30.00000000000000000000
$

a taxa de quadros do meu vídeo é de 30 fps.

margaret
fonte
2

A única coisa exata que consegui fazer é o seguinte:

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

Para ter certeza de que funciona com vídeo:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Lloyd Moore
fonte
Votei positivamente em sua resposta, mas isso só funcionará se o vídeo não contiver áudio. Se contiver, este funcionará:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

Desculpe pela resposta do necro, mas talvez precise disso (pois não encontrei uma solução para os lançamentos recentes do ffmpeg.

Com ffmpeg 3.3.4 descobri que pode encontrar com o seguinte:

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

No final, ele emitirá contagem de quadros. Funcionou para mim em vídeos com áudio. Ele fornece duas vezes uma linha "nb_frames", mas a primeira linha era a contagem real de quadros nos vídeos que testei.

acidrums4
fonte
Obrigado @ acidrums4. Verifiquei se esse método funciona com a versão mais recente do github que criei hoje.
Paul J
1

Eu uso o php_ffmpeg então consigo obter todos os tempos e todos os frames de um filme. Como abaixo

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

E então o detalhe está na página.

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

xingyue
fonte
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
fonte
A taxa de quadros é normalmente calculada a partir de dois parâmetros. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Arredondado por ffmpeg para: 23,98 Duração = horas * 3600 + minutos * 60 + segundos.remainder = 8177,91 Enquanto parâmetro de duração = 8177,794625 Mas Quadros = 24000/1001 * 8177,794625 = 196071 fornece o número exato de quadros. (Sem brincadeiras).
Gerard Wensink
0

linux

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

rubi

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