Como obtenho o número de quadros em um vídeo na linha de comando do linux?


30

Eu tenho um arquivo de vídeo e quero obter o número de quadros de vídeo nele. Eu posso usar ffmpegpara obter a duração do vídeo e do FPS. No entanto, não vejo nada óbvio para o número total de quadros.

Em teoria, deve-se conseguir multiplicar a duração (em segundos) pelo FPS para obter o número de quadros, mas, neste caso, a duração (34,43 segundos) e a taxa de quadros (29,97 fps) fornecem um não inteiro, o que me faz acho que estou fazendo algo errado.

Eu preciso ser capaz de fazer isso na linha de comando de maneira totalmente automatizada e não gráfica. Eu também preciso que isso seja bem exato, e não uma estimativa (se isso é possível com arquivos de vídeo)

Eu tentei usar tcprobeem alguns arquivos. Para alguns arquivos AVI, ele funciona, mas para alguns arquivos VOB, a saída do tcprobe não possui o número de quadros. Eu recebo esta saída:

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

sua equação fornecerá uma boa estimativa; basta arredondar o resultado de ponto flutuante para cima. se você precisar de um número exato de quadros, precisará examinar o arquivo diretamente - sua estimativa pode ser reduzida em um ou dois em qualquer direção, devido aos detalhes do codec de vídeo.
— quack quixote

são esses VOBs completos em um arquivo ou VOBs divididos em vários arquivos no estilo de DVD?
— quack quixote

Respostas:


17

Isso é horrível, estúpido e lento, mas parece funcionar:

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

Também funcionará corretamente em arquivos truncados e fluxos brutos (é por isso que você não obtém nada para arquivos .vob)


Isso é muito bom. Na minha experiência, não leva muito tempo. Um arquivo de 40 minutos leva cerca de <3 segundos para ser executado. Lembre-se de que "^ M" não são os 2 caracteres ^ e M, você deve pressionar Control-V e depois inserir. Em vez do seu comando, usei: 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 Seu comando falha se não houver espaço após o "frames ="
— Rory

1
No Ubuntu 12.04, versão ffmpeg git-2013-04-15-a4f03f0, você pode omitir ambos | tr ^M '\n'e |tail -n 1. Além disso, nenhum espaço depois frames=não falha. (Talvez alguma coisa mudou nos últimos quatro anos.)
— Camille Goudeseune

para mim este retorno cada vez que valores diferentes
— CAMOBAP

1
A solução Mediainfo funciona com VOB. Eu recomendaria isso. raiz @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count Contagem de quadros: 175715 Contagem de quadros: 183218
— kevinf

32

ffprobe pode ser usado para obter informações sobre um arquivo de mídia:

ffprobe -select_streams v -show_streams input.avi

Você obterá detalhes sobre o fluxo:

nb_frames=159697

Procure nb_framescom grep:

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

Isso funciona para avi, mp4 e etc. Para alguns contêineres, ele não mostra um valor válido, por exemplo, mpeg.

Nesse caso, isso funciona ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l


Boa ideia. Modifiquei um pouco o comando para selecionar apenas o fluxo de vídeo e filtrar a saída. Isso fornece apenas o número de quadros.
— slhck

1
Parabéns pela sua segunda solução que funciona com MPEG-2!
— 21315 Malat

1
Não funciona com contêineres MKV.
— Cenk Alti


Parece que a primeira abordagem falha nos arquivos codificados em VBR. A segunda abordagem é mais confiável.
— Elder Geek

16

Eu postei isso em outra pergunta . Usando a tcprobeferramenta (do transcodepacote), o número de quadros é incluído nas informações. Use a -iopção para obter um despejo de informações do arquivo:

$ 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

Observe o número de quadros aqui em duas linhas (2ª linha de saída e última linha de saída).


Parece uma boa resposta e funciona para alguns arquivos, mas para alguns arquivos VOB que tenho, não tenho esses dados na saída. Eu atualizei a questão com a saída fico
— Rory

Eu espero (mas não sei ao certo) que o tcprobe está examinando os cabeçalhos dos arquivos para obter essas informações. se não estiver incluído no cabeçalho, o tcprobe pode não tentar um cálculo para ele. boa pergunta; Gostaria de ter uma boa resposta para você.
— quack quixote

Isso parece não funcionar em arquivos codificados em VBR. Não recebo saída de contagem de quadros. Recebo resolução, proporção e taxa de quadros.
— Elder Geek

7

Descobri que mediainfo --fullscan inputfile | grep "Frame count"funciona muito bem para a maioria dos arquivos.

Os sistemas Debian podem instalá-lo com apt-get install mediainfo

Se você obtiver 2 linhas em vez de uma saída, a primeira linha é a faixa de vídeo e a segunda linha é a faixa de áudio. Parece que isso ocorre em arquivos com áudio de taxa de bits variável.

Testado em amostras .mkv, .m4v, .mp4, flv, vob e .avi na data da edição.

Fontes: Como recuperar informações de arquivos de vídeo da linha de comando no Linux? e teste sob os sabores do Ubuntu.

Você pode encontrar informações de mídia disponíveis para o seu sistema operacional aqui.


4

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

Adicione a duração. Poderia ser mais chique com sed / awk e quais não.

De nossos testes, posso dizer que, por enquanto, ele se mostrou o melhor e mais confiável. Você obtém uma contagem de quadros precisa e duração exata. Mesmo com taxa de quadros variável em que todas as outras ferramentas, como mediainfo, parecem loucas.


3

Descobri que o número de quadros é na verdade o dobro da duração de fps * (não faço ideia do porquê, ficaria feliz em saber).

Em um script meu, eu tenho:

# 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 sim, por algum motivo eu tenho que pegar a parte inteira. Não faz sentido, mas esse script sempre conseguiu converter meus vídeos adequadamente até o momento.


Como FPS significa Frames Por Segundo (ou shooter em primeira pessoa: D) e se houver 30 FPS, basta multiplicá-lo por quantos segundos estão no vídeo.
— John T

Sim John, eu pude descobrir isso, mas isso não explica por que eu tenho que multiplicá-lo por 2 para obter a quantidade certa de quadros ... No meu caso, depois de calcular a quantidade de quadros, iniciei o ffmpeg no segundo plano e analisou os logs para fazer uma barra de progresso. Os logs mostram quantos quadros passaram na conversão. Uma vez que todo o vídeo foi convertido, o frame # foi int (segundos * fps * 2), daí o meu código, mas eu gostaria de saber por que ;-)
— ℝaphink

isso é curioso; a tcprobesaída na minha resposta fornece o número de quadros exatamente como segundos * fps (arredondado para cima). Espero que você esteja vendo uma peculiaridade do ffmpeg. você tentou analisar o arquivo com outras ferramentas para ver se elas mostram o mesmo número de quadros?
— quack quixote

Hummm ... Interessante. Eu tentei um vídeo e consegui seconds*fps=1001.59e tcprobe=1002. Então, obviamente, tcprobeme diz que não preciso multiplicar por dois. Por que, então, o ffmpeg me fornece um número duas vezes maior nos logs durante a conversão?
— 21909 Dech

2
é filmagem entrelaçada? Nesse caso, existem dois campos por quadro e isso pode fornecer o número de campos.
— STIB

3

Testado no Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- derreter foi concebido como uma ferramenta de teste para a estrutura MLT, mas também é um poderoso editor de vídeo multitrack orientado à linha de comando. Também poderia ser usado como um media player minimalista para arquivos de áudio e vídeo.

  • -consumerid [: arg] [name = value] *
    Defina o consumidor (coletor)

  • xml - Defina o consumidor (coletor) como saída formatada em xml

  • <property name="length">nnnn</property>- mostra o número de quadros, onde nnnné substituído por um número inteiro igual ao número de quadros

Se você não derrete, pode instalá-lo no Ubuntu e em outros sistemas baseados no Debian com sudo apt-get install melt


1
Isso é muito curto, você deseja expandir o que faz, por que funciona etc.?
— David

Isso funciona bem em arquivos h264 mp4 que não fornecem a contagem de quadros via mediainfo -fullscan filename.
— Elder Geek

3

Diretamente com mediainfo, sem grep, sem espera, sem nada:

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

Para outras informações, consulte mediainfo --info-parameters


0

Você pode fazer isso adicionando e multiplicando os valores obtidos do ffprobe.

Nota: o ffprobe faz parte do libav (avconv) - a versão linux do ffmpeg.

#your command -
 ffprobe man.avi

Ao fazer isso, você obterá o número de quadros por segundo e também a duração do clipe.

Converta a duração do clipe em segundos e multiplique esse valor pelo número de quadros / segundo.

Lembre-se de arredondar o número para o mais próximo.


No Ubuntu 14.04 LTS ffprobenão estiver disponível, mas existe algo chamado avprobeem libav-tools(que também fornece avconv). Mas, ao meu lado, não imprime nenhum número de quadros, pelo menos não para os formatos que tentei. Apenas imprime, o que avprobe -iimprime também, e isso é apenas alguns pequenos detalhes sobre o formato, infelizmente. Mesmo com -v debugisso, apenas me informa algumas propriedades agradáveis ​​do meu hardware e software instalado, mas nenhuma informação interessante sobre o arquivo / fluxo a ser analisado. Talvez ele se esconda em algumas das inúmeras opções disponíveis. Quem sabe?
— Tino

O @Tino ffprobe está realmente disponível como parte do pacote ffmpeg. O avconv é um fork do ffmpeg e causou alguma confusão. Veja: stackoverflow.com/questions/9477115/…
— Elder Geek

@ElderGeek Para o Ubuntu 14.04 LTS, não existe ffmpegnos repositórios oficiais. O link que você forneceu indica corretamente: O FFmpeg retornou no Ubuntu 15.04 "Vivid Vervet". . No entanto, a situação agora mudou quando 16.04 LTS saiu.
— Tino

@ Tino Isso é realmente um fato. No entanto, eu não consideraria indisponível, não existe nos repositórios. Você vai notar que está disponível para Trusty (14.04) aqui: ffmpeg.org/download.html
— Elder Geek

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]

-2

Melhor método: (Direto calculando os parâmetros corretos, confirmados por 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"

Resultado ->

r_frame_rate=24000/1001
duration=8177.794625

Cálculo ->

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

Aqui

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

Saída

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

Eu recebo r_frame_rate = 25/1 duration = N / A
— Elder Geek
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.