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.