Como posso usar o ffmpeg para exportar imagens com precisão de um arquivo de vídeo?

4

Meu objetivo; exportar uma série de imagens de um arquivo de vídeo usando o ffmpeg. Acho que meu problema está relacionado a quadros por segundo e taxa de bits.

Eu tentei o seguinte comando: %código% mas de alguma forma, em um vídeo de 45 segundos, acabo com 47 imagens. É muito importante que eu acertar isso. Eu não saberei de antemão o que é o FPS apropriado ou taxas de bits, se eu precisar desses valores ao executar o comando, eu preciso ser capaz de puxá-los do ffmpeg de alguma forma.

Também considerei exportar TODAS as imagens no vídeo com ffmpeg -i myVideo.mp4 -r 1 images_%04d.jpg e dividir o número de imagens pelo total de segundos no vídeo. Isso me dará algo como 24,97, e eu irei arredondar para 25 e deletar 24 de cada 25 frames. Meu medo é que, se o arquivo for VBR e as partes de alta taxa de bits estiverem no início do vídeo, os quadros com os quais termino não corresponderão exatamente a 1 por segundo. Por exemplo, a 30ª imagem pode realmente aparecer no vídeo mais próxima do segundo 31.

 running ffmpeg -> ffmpeg -i "/videos/11.mp4" -s "352x264" "/images/image%06d.jpg"
FFmpeg version 0.6-4:0.6-2ubuntu6.1, Copyright (c) 2000-2010 the FFmpeg developers
  built on Mar 31 2011 18:43:47 with gcc 4.4.5
  configuration: --extra-version=4:0.6-2ubuntu6.1 --prefix=/usr --enable-avfilter --enable-avfilter-lavf 
--enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex 
--enable-libtheora --enable-libvorbis --enable-vaapi --enable-pthreads --enable-zlib --enable-libvpx 
--disable-stripping --enable-runtime-cpudetect --enable-gpl --enable-postproc --enable-x11grab 
--enable-libdc1394 --enable-shared --disable-static
  libavutil     50.15. 1 / 50.15. 1
  libavcodec    52.72. 2 / 52.72. 2
  libavformat   52.64. 2 / 52.64. 2
  libavdevice   52. 2. 0 / 52. 2. 0
  libavfilter    1.19. 0 /  1.19. 0
  libswscale     0.11. 0 /  0.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0

Seems stream 1 codec frame rate differs from container frame rate: 49938.00 (49938/1) -> 24.97 (24969/1000)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/videos/11.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
  Duration: 00:00:32.60, start: 0.000000, bitrate: 433 kb/s
    Stream #0.0(und): Audio: aac, 44100 Hz, stereo, s16, 127 kb/s
    Stream #0.1(und): Video: h264, yuv420p, 352x264 [PAR 1:1 DAR 4:3], 303 kb/s, 24.97 fps, 24.97 tbr, 24969 tbn, 49938 tbc
Output #0, image2, to '/images/image%06d.jpg':
  Metadata:
    encoder         : Lavf52.64.2
    Stream #0.0(und): Video: mjpeg, yuvj420p, 352x264 [PAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 90k tbn, 24.97 tbc
Stream mapping:
  Stream #0.1 -> #0.0
Press [q] to stop encodingframe=  176 fps=  0 q=24.8 size=      -0kB time=7.05 bitrate=  
-0.0kbits/s    ^Mframe=  312 fps=236 q=24.8 size=      -0kB time=12.50 bitrate=  -0.0kbits/s    
^Mframe=  316 fps=112 q=24.8 size=      -0kB time=12.66 bitrate=  -0.0kbits/s    ^Mframe=  322 
fps= 55 q=24.8 size=      -0kB time=12.90 bitrate=  -0.0kbits/s    ^Mframe=  327 fps= 39 q=24.8 
size=      -0kB time=13.10 bitrate=  -0.0kbits/s    ^Mframe=  331 fps= 33 q=24.8 size=      
-0kB time=13.26 bitrate=  -0.0kbits/s    ^Mframe=  336 fps= 31 q=24.8 size=      -0kB time=13.46 
bitrate=  -0.0kbits/s    ^Mframe=  339 fps= 27 q=24.8 size=      -0kB 
time=13.58 bitrate=  -0.0kbits/s    ^Mframe=  344 fps= 22 q=24.8 size=      -0kB 
time=13.78 bitrate=  -0.0kbits/s 

Alguém tem idéias de como obter resultados precisos em tempo exportando imagens de vídeo com ffmpeg? Obrigado!

    
por Jesse Smith 19.11.2011 / 03:48

3 respostas

1

Tem certeza de que está perdendo quadros? Seu vídeo de entrada é o h264 que suporta taxa de quadros variável. Para obter detalhes sobre cada quadro, recomendo usar o seguinte:

ffmpeg -i inputvideo -vf showinfo -acodec copy -vcodec mpeg2video temp.mp4

Dessa forma, você saberá quantos quadros seu filme tem.

Você pode evitar a taxa de quadros variável convertendo seu filme em um vídeo com taxa de quadros não variável, usando o argumento -r float e exportando as fotos (como fez no seu comando).

    
por 15.06.2012 / 06:44
1

Você precisa especificar manualmente um valor -vsync . A discrepância é mais provável devido à diferença na taxa de quadros variável / constante e nos timestamps de quadro. Se você tiver uma fonte VFR, o ffmpeg por padrão tentará segmentar uma taxa estimada (o valor tbr ) e derrubará ou duplicará quadros em um esforço para "suavizar" o movimento. Exportar quadros como imagens segue esse comportamento também. Algumas informações da documentação:

-vsync parameter

Video sync method. For compatibility reasons old values can be specified as numbers. Newly added values will have to be specified as strings always.

0, passthrough

Each frame is passed with its timestamp from the demuxer to the muxer.

1, cfr

Frames will be duplicated and dropped to achieve exactly the requested constant frame rate.

2, vfr

Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp.

drop

As passthrough but destroys all timestamps, making the muxer generate fresh timestamps based on frame-rate.

-1, auto

Chooses between 1 and 2 depending on muxer capabilities. This is the default method.

Como diz aqui, o ffmpeg selecionará -vsync -1 por padrão (para codificação de vídeo e exportação de imagens). O que você quer é um repasse direto sem alterações. Use -vsync 0 se você quiser manter todos os quadros como estão, sem quedas ou dupes. Você provavelmente receberá mensagens sobre DTS não monótono, mas isso pode ser amplamente ignorado. Aqui está um exemplo de comando para a saída de todos os quadros com precisão de um vídeo:

ffmpeg -i video.nut -f image2 -vsync 0 frame-%03d.tiff
    
por 17.04.2017 / 13:39
0

Eu observei um comportamento errático semelhante ao extrair imagens com o argumento -r.

Eu encontrei uma solução que funcionou para mim usando a opção -vf fps = X (com algumas notas importantes abaixo). Acredite ou não, o comportamento aqui parece mais previsível do que o comportamento com -r.

  1. Para gerar uma imagem a cada X segundos do vídeo de entrada, calcule o valor de ponto flutuante de 1 / X e execute:

ffmpeg -i input.mp4 -vf fps=1.0/x image-%04d.jpg

por exemplo, para obter duas imagens por segundo:

ffmpeg -i input.mp4 fps=0.5 image-%04d.jpg

Isso fará quase a coisa certa, note que:

  1. Um primeiro quadro extra é gerado, o que deve ser ignorado.
  2. Quadros são feitos a cada X segundos, onde X é o argumento para -vf fps=X , iniciando em X / 2 segundos.

Então, executando:

ffmpeg -i input.mp4 fps=1 image-%04d.jpg

Em um vídeo de 5 segundos, haverá 6 arquivos, o primeiro deve ser ignorado e o segundo e o sexto corresponderão aos timestamps: 0.5, 1.5, 2.5, 3.5 e 4.5.

Aqui está um vídeo de teste útil para depurar esse tipo de coisa:

link

    
por 13.10.2016 / 23:57

Tags