Jak mogę użyć ffmpeg do dokładnego eksportowania obrazów z pliku wideo?

4

Mój cel; wyeksportuj serię obrazów z pliku wideo za pomocą ffmpeg. Myślę, że mój problem dotyczy ramek na sekundę i szybkości transmisji.

Próbowałem następującej komendy: ffmpeg -i myVideo.mp4 -r 1 images_%04d.jpg ale jakoś na 45 sekundowym filmie kończę na 47 zdjęciach. To bardzo ważne, że rozumiem to dokładnie. Nie będę z góry wiedział, jakie są odpowiednie FPS lub szybkości transmisji bitów, jeśli potrzebuję tych wartości podczas uruchamiania polecenia, muszę być w stanie jakoś wyciągnąć je z ffmpeg.

Rozważałem również eksport WSZYSTKICH obrazów na wideo za pomocą ffmpeg -i myVideo images_%04d.jpg i podzielenie liczby obrazów przez całkowitą liczbę sekund w filmie. To da mi coś w rodzaju 24,97, a zaokrąglę do 25 i usunę 24 z 25 klatek. Obawiam się, że jeśli plik jest VBR, a części o wysokiej szybkości transmisji bitów znajdują się na początku filmu, ramki, które kończę, nie będą dokładnie odpowiadały 1 na sekundę. Na przykład 30. obraz może rzeczywiście pojawić się w filmie bliżej drugiego 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 

Czy ktoś ma pomysły, jak uzyskać dokładne wyniki, eksportując obrazy z wideo za pomocą ffmpeg? Dzięki!

Jesse Smith
źródło
Co to jest kodek wideo?
Steven Penny
1
Może być spokrewniony… zdecydowanie powinieneś zaktualizuj swoją wersję FFmpeg .
slhck

Odpowiedzi:

1

Czy na pewno tracisz ramki? Twój film wejściowy to h264, który obsługuje zmienną częstotliwość klatek. aby uzyskać szczegółowe informacje na temat każdej ramki, polecam następujące czynności:

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

W ten sposób dowiesz się, ile klatek ma Twój film.

Możesz uniknąć zmiennej liczby klatek na sekundę, konwertując film na wideo o zmiennej liczbie klatek, używając -r float argument, a następnie eksportowanie zdjęć (jak w poleceniu).

E.G.
źródło
1

Musisz ręcznie określić a -vsync wartość. Rozbieżność jest najprawdopodobniej spowodowana różnicą w zmiennej / stałej szybkości klatek i znacznikach czasu ramki. Jeśli masz źródło VFR, ffmpeg domyślnie spróbuje wycelować szacunkowy współczynnik ( tbr wartość) i upuszcza lub powiela ramki w celu „wygładzenia” ruchu. Eksportowanie klatek jako obrazów jest również zgodne z tym zachowaniem. Niektóre informacje z dokumentacji:

-vsync parametr

Metoda synchronizacji wideo. Ze względów kompatybilności stare wartości można określić jako liczby. Nowo dodane wartości będą zawsze musiały być określone jako łańcuchy.

0, przejście

Każda ramka jest przekazywana wraz z datownikiem z demuxera do muxera.

1, cfr

Ramki będą duplikowane i upuszczane, aby uzyskać dokładnie żądaną stałą szybkość klatek.

2, Vfr

Ramki są przekazywane z datownikiem lub upuszczane, aby zapobiec temu samemu znacznikowi czasu dla 2 klatek.

upuszczać

Jako przejście, ale niszczy wszystkie znaczniki czasu, dzięki czemu muxer generuje nowe znaczniki czasu na podstawie szybkości klatek.

-1, auto

Wybiera od 1 do 2 w zależności od możliwości multipleksera. Jest to metoda domyślna.

Jak mówi tutaj, ffmpeg wybierze -vsync -1 domyślnie (zarówno dla kodowania wideo, jak i eksportowania obrazów). To, czego chcesz, to proste przejście bez zmian. Posługiwać się -vsync 0 jeśli chcesz zachować każdą ramkę bez żadnych kropli lub duplikatów. Prawdopodobnie otrzymasz wiadomości o nie Monotonicznym DTS, ale można to w dużej mierze zignorować. Oto przykładowe polecenie do dokładnego wyświetlania wszystkich klatek z filmu:

ffmpeg -i video.nut -f image2 -vsync 0 frame-%03d.tiff
HDL
źródło
0

Zaobserwowałem podobne błędne zachowanie podczas wyodrębniania obrazów za pomocą argumentu -r.

Znalazłem rozwiązanie, które działało dla mnie, używając opcji -vf fps = X (z kilkoma ważnymi uwagami poniżej). Wierzcie lub nie, zachowanie tutaj wydaje się bardziej przewidywalne niż zachowanie z -r.

  1. Aby wygenerować obraz co X sekund z wejściowego wideo, oblicz wartość zmiennoprzecinkową 1 / X i uruchom:

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

na przykład, aby uzyskać 2 obrazy na sekundę:

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

To zrobi prawie właściwą rzecz, zauważ, że:

  1. Generowana jest dodatkowa pierwsza ramka, którą należy zignorować.
  2. Ramki są wykonywane co X sekund, gdzie X jest argumentem -vf fps=X, zaczynając od X / 2 sekund.

Tak więc działa:

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

W przypadku 5-sekundowego wideo powstanie 6 plików, pierwszy powinien zostać zignorowany, a 2–6 będzie oznaczać znaczniki czasu: 0,5, 1,5, 2,5, 3,5 i 4,5.

Oto przydatne wideo testowe do debugowania tego rodzaju rzeczy:

https://drive.google.com/file/d/0B56RokrDs3xabS1TS19wRjlBaVk/view?usp=sharing

deadcode
źródło