Extracción del índice de fotogramas clave de un video usando ffmpeg


17

Estoy usando ffmpeg para extraer fotogramas clave de un video. Este es el comando:

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

¿Cómo puedo obtener el índice de cada fotograma clave extraído en el video? Por ejemplo, para el primer cuadro I, el índice sería 0, para el segundo sería 24, etc.



¿Considera el uso de ffprobe y luego procesa la salida para obtener el índice?
dstob

@dstob, ¿podría explicar más sobre lo que quiere decir? como soy nuevo en ffmpeg
Faten Khalifa

@LordNeckbeard El número de cuadro en los cuadros de video, ej. el primer cuadro del video estaría en el índice 0 Quiero saber el índice de cada cuadro clave en los cuadros de video.
Faten Khalifa

¿Desea que se imprima el número de fotograma en la miniatura (en la propia imagen)?
lema

Respuestas:


21

Como mencionó @dstob, puede usar ffprobepara obtener los I-frames y su información asociada. ffprobeviene con algunas de las compilaciones estáticas en la página de descarga y también se puede construir desde la fuente.

Esto supone que estás en Linux / Unix:

Extraer cuadros y tipos de cuadros

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

El grepcomando filtra las líneas con Iellas y cuenta su índice (usando la -nopción). El cutcomando selecciona solo la primera columna de la salida (el índice). Tenga en cuenta que este índice se basa en 1, no en 0.

Cambiar el nombre de los archivos de salida según el índice

En realidad, puede canalizar estos índices a una lista:

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

Luego haga una lista de todas las miniaturas también:

ls -1 thumbnails*.jpeg > thumbnails.txt

Luego pegue esos dos juntos:

paste thumbnails.txt frame_indices.txt > combined.txt

La lista ahora contiene el nombre de la miniatura y el índice. Realice un cambio de nombre basado en eso:

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

Lo anterior cambiará el nombre thumbnail-01.jpega thumbnail-0.jpeg. Tenga en cuenta que no hay relleno de cero en el índice de salida. Si desea ponerlo a cero, digamos, 5 dígitos, use printf:

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

En Windows, haría exactamente lo mismo ffprobepero analizaría la salida de manera diferente. Sin embargo, no tengo idea de cómo realizar el cambio de nombre allí.


Se muestra este error: 'grep' no se reconoce como un comando interno o externo, un programa operativo o un archivo por lotes.
Faten Khalifa

2
Eso es porque estás en Windows. Como dije, esta respuesta asume Linux o Unix. No estabas siendo más específico en tu pregunta. Puede lograr lo mismo en Windows utilizando Cygwin o capas similares de GNU / Linux para Windows.
slhck

Esta es una gran ayuda, gracias. Una corrección: creo que los índices en su primer comando están desactivados por un factor de tres, porque hay una [FRAME]línea y una [/FRAME]línea para cada pict_typelínea.
Jack O'Connor

2
@ JackO'Connor Solo hay una línea por cuadro si usa la -of csvopción para ffprobe. Sin embargo, lo que está describiendo es el formato de salida predeterminado.
slhck

0

Si desea utilizar FFMPEG como se indicó originalmente, puede enumerar todo o una lista parcial, así como crear jpg con lo siguiente:

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"

Retirar -t 15sin límite de tiempo o cambiar a su gusto. Eliminar -s 160x90 -f image2 thumbnail-%02d.jpego cambiar para adaptarse a la eliminación de miniaturas.


En Windows 7 CMD, esto falla en el \. Cambiar \ a ^ provoca un error en: I ". ¿Tiene una versión que funcione en Windows?
ChrisJJ
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.