Jak wyodrębnić jedną klatkę wideo co N sekund do obrazu?

71

Jak mogę przekonwertować plik wideo na sekwencję obrazów, na przykład jedną klatkę co N sekund. Czy mplayer lub ffmpeg mogą to zrobić? Użyłem MPlayera do ręcznego robienia zrzutów ekranu, ale chciałbym zautomatyzować to w przypadku długiego filmu.

Liam
źródło
Zobacz to powiązane pytanie dotyczące wyboru jakości obrazów: stackoverflow.com/questions/10225403/…
Pierz

Odpowiedzi:

70

Jest to bardzo proste z ffmpeg i może generować jedną klatkę co N sekund bez dodatkowego skryptu. Aby wyeksportować jako sekwencję obrazów, po prostu użyj myimage_%04d.pnglub jako wyjście. %0xdBit jest przetwarzany na zero wyściełane całkowitą xcyfr - przykładzie I otrzymano dostaje wynik jako

  • myimage_0000.png,
  • myimage_0001.png,
  • myimage_0002.png

    itp..

Możesz użyć wielu formatów zdjęć, png, jpeg, tga, cokolwiek (zobacz ffmpeg -formatspełną listę).

Ok, więc teraz wiemy, jak wyeksportować film jako sekwencję obrazów, ale powiedzmy, że nie chcemy eksportować każdej klatki?

Sztuką jest po prostu zmiana liczby klatek na sekundę wyjścia na cokolwiek chcemy, korzystając z -r nopcji gdzie nliczba klatek na sekundę. 1 klatka na sekundę -r 1, jedna klatka co cztery sekundy -r 0.25, jedna klatka co dziesięć sekund -r 0.1i tak dalej.

Podsumowując, tak wyglądałoby zapisanie jednej klatki input.movco cztery sekundy output_0000.png, output_0001.pngitd .:

ffmpeg -i input.mov -r 0.25 output_%04d.png

Należy pamiętać, że -r 0.25opcja idzie po tej -i input.movczęści, ponieważ jest kontrolowanie klatek na wyjściu . Jeśli umieścisz go przed wejściem, będzie traktował plik wejściowy tak, jakby miał określoną częstotliwość klatek.

Zmień% xd do wielu cyfr jednak trzeba, np jeśli komenda stworzy ponad 10.000 klatek zmienić %04dsię %05d. Działa to również w przypadku plików wejściowych, które są sekwencjami obrazów. Przeczytaj więcej tutaj .

Użytkownicy systemu Windows : w wierszu polecenia użyj%

przykład: ffmpeg -i inputFile.mp4 -r 1 outputFile_%02d.png

W skryptach CMD i BAT należy używać %%

przykład: ffmpeg -i inputFile.mp4 -r 1 outputFile %%02d.png

Więc podwój %%w skryptach i pojedynczo %w interaktywnym wierszu poleceń. Błąd w obu sytuacjach spowoduje błąd.

dźgnięcie
źródło
W co powinienem włożyć, -rjeśli chcę eksportować każdą ramkę? Jeśli znam FPS tego filmu, to chyba go wprowadzam, ale co jeśli nie?
Tomáš Zato
4
W ogóle nie używaj flagi -r. Następnie FFMPEG użyje częstotliwości klatek pliku wejściowego.
stib
2
Zauważ, że naprawdę będziesz chciał do tego użyć jpegs, chyba że jesteś pewien png, że tego chcesz. W moim przypadku jpegrozmiar każdego z nich wynosił około 50 KB, a rozmiar pngokoło 2 MB.
mlissner
5
zaletą pngs jest kompresja bezstratna, więc jeśli używasz sekwencji obrazów jako pośredniej i nie przeszkadza ci dodatkowy rozmiar, wtedy możesz użyć png.
stib
Warto dodać, że -q:v 1jest to bardzo przydatna opcja tutaj, jak w superuser.com/questions/318845/…
Nikolay Shmyrev
27
mplayer -vo jpeg -sstep 5 file.avi

zapisze ramkę jako plik jpeg co 5 sekund.

Jednak nie zatrzyma się na końcu pliku, będzie kontynuował tworzenie kopii ostatniej klatki. Aby tego uniknąć, znajdź czas trwania filmu w sekundach, używając innego odtwarzacza lub za pomocą mplayera:

mplayer -vo null -ao null -frames 0 -identify file.avi

i poszukaj linii takiej jak „ID_LENGTH = 147,00”.

Odejmij 2 od długości i użyj tej wartości dla -endposopcji. Na przykład dla 147 sekund wideo:

mplayer -vo jpeg -sstep 5 -endpos 145 file.avi
Liam
źródło
brzmi to jak błąd mplayera. niezłe obejście.
szarlatan
Czy mógłbyś przynajmniej wspomnieć, na którym systemie operacyjnym używasz tego polecenia?
Tomáš Zato,
To było 5 lat temu, ale prawdopodobnie był to najnowszy wówczas Ubuntu Desktop, Ubuntu 10.4.
Liam,
Jak mogę wybrać kroki krótsze niż 1s. Akceptuje tylko liczby całkowite.
fcpenha
Obecnie mpv --vo=image --sstep=5 movie.mkvdziała świetnie bez wyżej wspomnianego błędu ( mpv jest rozwidleniem mplayera) przy użyciu mpv 0.27.0 na Debianie.
Adam Katz,
11

Za pomocą ffmpegmożesz wykonać następujące czynności:

ffmpeg -ss 4 -i input.avi -s 320x240 -frames:v 1 output.jpg

To polecenie generuje miniaturę JPG o rozmiarze 320 × 240 w 4. sekundzie filmu. Umieść to w skrypcie, który zmienia czas i nazwę pliku i gotowe.

Więcej informacji: Utwórz miniaturę co X sekund filmu

Nifle
źródło
Wydaje się, że robi to, co chcę, ale z jednym problemem. Przetwarza plik od samego początku przy każdej iteracji, spowalniając się wykładniczo.
Liam
@Liam - Czy to pomaga, jeśli pozostawiasz czas przesunięcia w spokoju (ustaw go na 1) i używasz -ss positionflagi, aby szukać dalej w pliku? -ss Seek to given time position in seconds. hh:mm:ss[.xxx] syntax is also supported
Nifle
1
@liam: wstaw -ssprzed, -iaby wyszukiwanie odbywało się przed dekodowaniem wejściowego wideo. to powinno przyspieszyć. źródło
quack quixote
2
Jest lepszy, znacznie szybszy sposób, aby to zrobić za pomocą ffmpeg. Zobacz moją odpowiedź poniżej.
stib
rozwiązaniem stib jest najlepsze IMO.
Griffin,
8

Jeśli szukasz swoistego arkusza kontaktowego i pracujesz z systemem operacyjnym podobnym do Uniksa, możesz użyć tego skomplikowanego skryptu, zwanego do punktu Video Contact Sheet * NIX , short vcs .

W tle używa również ffmpeg(domyślnie) lub mplayer, dlatego może obsługiwać wiele formatów wideo. Automatyzuje proces przechwytywania nieruchomych obrazów z filmu i komponuje je w obraz z pewnym nagłówkiem i stopką. Możesz wybrać np. Ile zdjęć chcesz lub alternatywnie różnice czasowe między nimi.

Przez 10 minut wywoływanie wygląda następująco:

vcs -i 10m input.avi

Sprawdź pełną listę opcji wiersza poleceń dla niektórych innych poprawek.

Oto przykładowy formularz kontaktowy pobrany ze strony głównej :

wprowadź opis zdjęcia tutaj

mpy
źródło
7

W wersji VLC 1.1.0 i nowszej możesz użyć filtra wideo sceny:

vlc C:\video\to\process.mp4 --rate=1 --video-filter=scene --vout=dummy --start-time=10 --stop-time=11 --scene-format=png --scene-ratio=24 --scene-prefix=snap --scene-path=C:\path\for\snapshots\ vlc://quit

Powyższe zapisuje 1 z każdych 24 klatek (--scene-ratio = 24), zaczynając od 00:00:10 i kończąc o 00:00:11.

Właśnie przetestowałem i potwierdziłem, że działa z VLC 2.0.3 na świeżej instalacji Windows 8 (nie mam żadnych dodatkowych wtyczek wideo ani oprogramowania).

Pełna dokumentacja: http://wiki.videolan.org/How_to_create_thumbnails

Michael
źródło
2

VirtualDub może to dla Ciebie zrobić

File-> Export->Image sequence

wprowadź opis zdjęcia tutaj

Shevek
źródło
Czy to zapisze każdą klatkę jako obraz?
Liam
tak, każda klatka.
Shevek
Muszę pominąć większość ramek, wyświetlenie wszystkich ramek zajmie zbyt dużo miejsca w pamięci. Potrzebuję tylko jednej klatki co kilka sekund.
Liam
1

Możesz także spróbować tego

z wiersza poleceń VLC ...

vlc "C: \ YOUR \ file \ path \ file.avi" -V obraz - przedrostek -obraz-wyjścia-nazwa = nazwa-cap-proporcji = 60

file.avi to wideo, z którego chcesz przechwycić, capname to przedrostek zapisanych obrazów, możesz chcieć się bawić ze współczynnikiem (60 oznacza, że ​​przechwycono 1 z 60 obrazów) Możesz na przykład dodać więcej poleceń, na przykład - image-out-format jpeg zapisze twoje kapsle jako jpegs zamiast pngs, --snapshot-path pozwala ci wybrać, gdzie zapisać kapsle.

Źródło powyżej

Nifle
źródło
Otrzymałem ten komunikat: Nie można załadować opcji wiersza polecenia, sprawdź, czy są one prawidłowe.
Liam
Na Ubuntu dostałem ten komunikat: nieznana opcja lub brak obowiązkowego argumentu `--image-out-prefix = capname '
Liam
1

Możesz pomijać ramki w VirtualDub. Wystarczy użyć opcji „Decimate By” znajdującej się w menu Wideo -> Liczba klatek na sekundę. Na przykład, jeśli ustawisz „Decimate By 100”, a następnie użyj polecenia Plik -> Eksportuj -> Sekwencja obrazów, zapisuje tylko co 100 klatkę.

Alex
źródło