Wyodrębnianie indeksu klatek kluczowych z wideo za pomocą ffmpeg

17

Używam ffmpeg do wydobywania klatek kluczowych z wideo. To jest polecenie:

ffmpeg -i test2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 160x90 -f image2 thumbnails-%02d.jpeg

Jak mogę pobrać indeks każdej klatki kluczowej z filmu? Na przykład dla pierwszej ramki I indeks wynosiłby 0, dla drugiej 24. Itd.

Faten Khalifa
źródło
możliwy duplikat superuser.com/questions/669716/…
user236012
Czy chcesz użyć ffprobe, a następnie przetworzyć dane wyjściowe, aby uzyskać indeks?
dstob
@dstob czy możesz wyjaśnić więcej o tym, co masz na myśli? jak jestem nowy w ffmpeg.
Faten Khalifa
@ LordNeckbeard Numer klatki w klatkach wideo, np. pierwsza klatka wideo miałaby indeks 0 Chcę poznać indeks każdej klatki kluczowej w klatkach wideo.
Faten Khalifa
Chcesz, aby numer klatki był drukowany na miniaturze (na samym obrazie)?
llogan

Odpowiedzi:

21

Jak wspomniano o @dstob, możesz użyć, ffprobeaby uzyskać ramki I i powiązane z nimi informacje. ffprobejest dostarczany z niektórymi statycznymi kompilacjami na stronie pobierania i może być również zbudowany ze źródła.

Zakłada się, że korzystasz z systemu Linux / Unix:

Wyodrębnij ramki i typy ramek

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1

grepPolecenia filtruje linie z Inimi, i liczy ich indeks (używając -nopcji). cutPolecenie wybiera pierwszą kolumnę tylko wyjście (indeks). Zauważ, że ten indeks jest oparty na 1, a nie na 0.

Zmień nazwę plików wyjściowych na podstawie indeksu

Możesz właściwie potokować te indeksy do listy:

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1 > frame_indices.txt

Następnie utwórz listę wszystkich miniatur:

ls -1 thumbnails*.jpeg > thumbnails.txt

Następnie wklej te dwa razem:

paste thumbnails.txt frame_indices.txt > combined.txt

Lista zawiera teraz nazwę miniatury i indeks. Wykonaj zmianę nazwy na podstawie:

while read -r thumbnail index; do
  newIndex=$(echo $index - 1 | bc) # subtract 1 from the index
  mv -- "$thumbnail" "thumbnail-$newIndex.jpeg"  # rename file
done < combined.txt

Powyższe zmieni nazwę thumbnail-01.jpegna thumbnail-0.jpeg. Zauważ, że na wskaźniku wyjściowym nie ma wypełnienia zerami. Jeśli chcesz wyzerować go do, powiedzmy, 5 cyfr, użyj printf:

newIndex=$(printf '%05d' $(echo $index - 1 | bc))

W systemie Windows zrobiłbyś dokładnie to samo, ffprobeale analizowałbyś dane wyjściowe w inny sposób. Nie mam jednak pojęcia, jak przeprowadzić tam zmianę nazwy.

slhck
źródło
Ten błąd jest wyświetlany: „grep” nie jest rozpoznawany jako polecenie wewnętrzne lub zewnętrzne, program operacyjny lub plik wsadowy.
Faten Khalifa
2
To dlatego, że korzystasz z systemu Windows. Tak jak powiedziałem, ta odpowiedź zakłada, że ​​Linux lub Unix. Nie byłeś bardziej szczegółowy w swoim pytaniu. Możesz to samo osiągnąć w systemie Windows za pomocą Cygwin lub podobnych warstw GNU / Linux dla systemu Windows.
slhck
To ogromna pomoc, dzięki. Jedna korekta: Myślę, że wskaźniki w pierwszym poleceniu są wyłączone trzykrotnie, ponieważ dla każdej linii jest [FRAME]linia i linia. [/FRAME]pict_type
Jack O'Connor
2
@ JackO'Connor Jest tylko jedna linia na ramkę, jeśli użyjesz -of csvopcji dla ffprobe. Opisujesz jednak domyślny format wyjściowy.
slhck,
0

Jeśli chcesz używać FFMPEG, jak pierwotnie stwierdzono, możesz wyświetlić listę wszystkich lub części, a także utworzyć plik jpg z następującymi elementami:

ffmpeg.exe \
  -i "C:\Users\UserName\Desktop\jpegs and list\VideoName.mp4" \
  -t 15 \
  -vf select="eq(pict_type\,PICT_TYPE_I)" \
  -vsync 2 \
  -s 160x90 \
  -f image2 thumbnails-%02d.jpeg \
  -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"

Usuń -t 15bez ograniczenia czasowego lub zmień na odpowiedni. Usuń -s 160x90 -f image2 thumbnail-%02d.jpeglub zmień, aby dopasować do usuwania miniatur.

Budman 1
źródło
W Windows 7 CMD nie udaje się to w \. Zmiana \ na ^ powoduje błąd przy: I ". Czy masz wersję, która działa w systemie Windows?
ChrisJJ