Estrarre l'indice dei fotogrammi chiave da un video usando ffmpeg


17

Sto usando ffmpeg per estrarre i fotogrammi chiave da un video. Questo è il comando:

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

Come posso ottenere l'indice di ciascun fotogramma chiave estratto nel video? Ad esempio, per il primo I-frame, l'indice sarebbe 0, per il secondo sarebbe 24, ecc.



Cerca di usare ffprobe, quindi pubblica l'output per ottenere l'indice?
dstob,

@dstob potresti spiegarmi di più su cosa intendi? come sono nuovo di ffmpeg.
Faten Khalifa,

@LordNeckbeard Il numero di frame nei frame video, ad es. il primo fotogramma del video sarebbe sull'indice 0 Voglio sapere l'indice di ciascun fotogramma chiave nei fotogrammi video.
Faten Khalifa

Vuoi che il numero di fotogramma venga stampato sulla miniatura (sull'immagine stessa)?
Llogan

Risposte:


21

Come menzionato @dstob, è possibile utilizzare ffprobeper ottenere gli I-frame e le informazioni ad essi associate. ffprobeviene fornito con alcune build statiche nella pagina di download e può essere compilato anche dal sorgente.

Questo presuppone che tu sia su Linux / Unix:

Estrai frame e tipi di frame

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

Il grepcomando filtra le righe al Iloro interno e conta il loro indice (usando l' -nopzione). Il cutcomando seleziona solo la prima colonna dell'output (l'indice). Si noti che questo indice è basato su 1, non su 0.

Rinomina i file di output in base all'indice

Puoi effettivamente reindirizzare questi indici a un elenco:

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

Quindi fai anche un elenco di tutte le anteprime:

ls -1 thumbnails*.jpeg > thumbnails.txt

Quindi incollali insieme:

paste thumbnails.txt frame_indices.txt > combined.txt

L'elenco ora contiene il nome della miniatura e l'indice. Eseguire una ridenominazione in base a ciò:

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

Quanto sopra verrà rinominato thumbnail-01.jpegin thumbnail-0.jpeg. Si noti che non vi è alcun zero padding sull'indice di output. Se vuoi azzerarlo a, diciamo, a 5 cifre, usa printf:

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

Su Windows, faresti esattamente lo stesso con ffprobema analizzi l'output in modo diverso. Non ho idea di come eseguire la ridenominazione lì però.


Questo errore viene visualizzato: 'grep' non viene riconosciuto come comando interno o esterno, programma eseguibile o file batch.
Faten Khalifa,

2
Questo perché sei su Windows. Come ho detto, questa risposta presuppone Linux o Unix. Non eri più specifico nella tua domanda. Puoi ottenere lo stesso su Windows usando Cygwin o layer GNU / Linux simili per Windows.
slhck

Questo è di grande aiuto, grazie. Una correzione: penso che gli indici nel tuo primo comando siano disattivati ​​di un fattore tre, perché c'è una [FRAME]linea e una [/FRAME]linea per ogni pict_typelinea.
Jack O'Connor,

2
@ JackO'Connor C'è solo una riga per frame se usi l' -of csvopzione per ffprobe. Quello che stai descrivendo è il formato di output predefinito, però.
slhck,

0

Se si desidera utilizzare FFMPEG come indicato in origine, è possibile elencare tutto o l'elenco parziale, nonché creare jpg con quanto segue:

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"

Rimuovere -t 15senza limiti di tempo o modificare in base alle proprie esigenze. Rimuovi -s 160x90 -f image2 thumbnail-%02d.jpego modifica per adattarlo alla rimozione delle miniature.


In Windows 7 CMD, questo non riesce in \. La modifica di \ in ^ provoca un errore in: I ". Hai una versione che funziona su Windows?
ChrisJJ,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.