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.


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.


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

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


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


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


2

VirtualDub może to dla Ciebie zrobić

File-> Export->Image sequence

wprowadź opis zdjęcia tutaj


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


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ę.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.