Obtener el recuento de cuadros con ffmpeg

112

¿Alguien sabe cómo obtener la cantidad de fotogramas totales de un archivo de video usando ffmpeg? La salida de renderizado de ffmpeg muestra el fotograma actual y necesito el recuento de fotogramas para calcular el progreso en porcentaje.

Hansl
fuente
1
superuser.com/questions/84631/...
Ciro Santilli郝海东冠状病六四事件法轮功

Respuestas:

158

Nota: La presencia de una lista de edición en MP4 / M4V / M4A / MOV puede afectar su número de fotograma. Consulte Editar listas a continuación.


ffprobe: consulta el contenedor

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Este es un método rápido.
  • No todos los formatos (como Matroska) informarán el número de fotogramas que resultan en la salida de N/A. Consulte los otros métodos que se enumeran a continuación.

ffprobe: cuenta el número de fotogramas

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Este es un método lento.
  • Agregue la -skip_frame nokeyopción de contar solo los fotogramas clave.

ffmpeg: cuenta el número de fotogramas

Si no lo tiene ffprobe, puede usar ffmpegen su lugar:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Este es un método algo rápido.
  • Consulte frame=cerca del final de la salida de la consola.
  • Agregue la -discard nokeyopción de entrada (antes -i) para contar solo los fotogramas clave.

Editar listas

Ignore la lista de edición MP4 / M4V / M4A / MOV con la -ignore_editlist 1opción de entrada. El valor predeterminado es no ignorar la lista de edición.

Que significan las opciones de ffprobe

  • -v error Esto oculta la salida de "información" (información de la versión, etc.) lo que facilita el análisis.

  • -count_frames Cuente el número de fotogramas por flujo e infórmelo en la sección de flujo correspondiente.

  • -select_streams v:0 Seleccione solo la transmisión de video.

  • -show_entries stream=nb_frameso -show_entries stream=nb_read_framesMostrar solo la entrada para nb_frameso nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Establezca el formato de salida (también conocido como el "escritor") en default, no imprima la clave de cada campo ( nokey=1) y no imprima el encabezado y pie de página de la sección ( noprint_wrappers=1). Hay alternativas más cortas como -of csv=p=0.

Ver también


información de los medios

La conocida mediainfoherramienta puede generar el número de fotogramas:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4Box

Para archivos MP4 / M4V / M4A.

MP4Box de gpac puede mostrar el número de fotogramas:

MP4Box -info input.mp4

Consulte la Media Infolínea en la salida para la transmisión de video en cuestión:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

En este ejemplo, la secuencia de video tiene 2525 cuadros.


caja

Para archivos MP4 / M4V / M4A / MOV.

boxdumperes una sencilla herramienta de l-smash. Producirá una gran cantidad de información. En la stszsección del cuadro de tamaño de muestra, consulte sample_countel número de fotogramas. En este ejemplo, la entrada tiene 1900 fotogramas de video:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Tenga en cuenta que un archivo puede tener más de un stszátomo.
llogan
fuente
5
O, si desea más velocidad y si nb_frames es lo suficientemente confiable, simplifique como:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
juanitogan
Esto genera la respuesta dos veces para mí (es decir, 2600 \ n 2600). ¿Alguna razón en particular por eso estaría sucediendo?
jbodily
@jbodily ¿Mi ejemplo o el de juanitogan? No puedo duplicarlo usando tampoco. No hay mucho con qué trabajar aquí.
llogan
+1, sobre todo porque, a diferencia de muchas otras respuestas sobre cualquier herramienta de línea de comando, esta en realidad explica todas las opciones de la línea de comando. Gracias.
Ray
1
Tenga en cuenta que la primera opción, consultar el contenedor, en realidad procesa el archivo debido a count_frames. Vea el comentario de @juanitogan.
aggieNick02
23

En Unix, esto funciona a la perfección:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
atáxico
fuente
3
Realmente uno bonito. Simplemente no es necesario copiar la transmisión de audio. Puede utilizar -an instat.
rekire
1
@PrakharMohanSrivastava Verifique esta respuesta
Antonio
4
En realidad, esto parece rápido y confiable:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Timothy Zorn
1
@Michael, gracias por la sonrisa con mi café de la mañana :-)
Lloyd Moore
1
@TimothyZorn ¡Me alegraste el día!
Mladen Danic
13

Calcúlalo en función del tiempo.

Eso es lo que hago y funciona muy bien para mí y para muchos otros). Primero, busque la duración del video en el siguiente fragmento:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

Debería poder encontrar de manera consistente y segura Duration: hh:mm:ss.nnpara determinar el tamaño del videoclip de origen. Luego, para cada línea de actualización (CR, no LF) puede analizar el texto para la marca de tiempo actual en la que se encuentra:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

Solo tenga cuidado de no esperar siempre un resultado perfecto de estas líneas de estado. Pueden incluir mensajes de error como aquí:

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

Una vez que usted tiene el tiempo, es simple matemática: time / durration * 100 = % done.

Stu Thompson
fuente
1
Disculpe por ser estúpido, pero ¿cómo puedo hacer el tiempo / duración cuando la duración está en formato hh: mm: ss.nn y el tiempo es siempre formato xx.yy?
Omar Ali
2
@Omar, como desarrollador de .NET, lo que hago es crear un archivo a TimeSpanpartir de él y luego usar currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). El TimeSpan también proporciona una potente función de análisis, compruébalo
Shimmy Weitzhandler
excelente solución, mi tiempo está en hh: mm: ss: ms así que supongo que en estos 3 años FFMPEG mejoró el formato de tiempo de salida.
ElektroStudios
1
Tenga en cuenta que la salida de la consola puede decir 29,97, pero es la abreviatura de 30000/1001. Lo mismo para 23,98 que es 24000/1001 y 59,94 es 60000/1001.
llogan
Como nota, esto no funciona para videos de velocidad de fotogramas variable (obviamente).
Timothy Zorn
8

No todos los formatos almacenan su recuento de fotogramas o la duración total, e incluso si lo hacen, el archivo puede estar incompleto, por lo que ffmpeg no detecta ninguno de ellos con precisión de forma predeterminada.

En su lugar, intente buscar el final del archivo y lea la hora, luego cuente la hora actual mientras avanza.

Alternativamente, puede probar AVFormatContext->nb_index_entrieso la duración detectada, que debería funcionar en AVI / MOV bien al menos sin daños, o la biblioteca FFMS2, que probablemente sea demasiado lenta para molestarse en una barra de progreso.

alex extraño
fuente
8

Prueba algo como:

ffmpeg -i "path to file" -f null /dev/null

Escribe el número de fotograma en stderr, por lo que puede recuperar el último fotograma de este.

a1kmm
fuente
8

Puede usar ffprobe para obtener el número de fotograma con los siguientes comandos

  1. primer método

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

que dicen imprimir datos en jsonformato

select_streams vle dirá ffprobeque nos brinde videodatos de transmisión y, si los elimina, también le brindará audioinformación

y la salida será como

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2. puedes usar

ffprobe -v error -show_format -show_streams video_name

que le dará datos de flujo, si desea información seleccionada como velocidad de fotogramas, use el siguiente comando

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

que dan una base numérica en la información de su video, el problema es que cuando usa este método, es posible que obtenga una N/Asalida como.

para obtener más información, consulte esta página FFProbe Tips

Hadi Rasekh
fuente
4

prueba esto:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Julien
fuente
No funciona con *.ts. La salida es una línea vacía.
Victor Polevoy
3

Dado que mi comentario recibió algunos votos a favor, pensé que lo dejaría como respuesta:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

Esto debería ser rápido, ya que no se está realizando ninguna codificación. ffmpegsimplemente demux el archivo y leerá (decodificará) el primer flujo de video lo más rápido posible. El primer grepcomando tomará el texto que muestra el marco. El segundo grepcomando tomará solo el número de eso. El tailcomando solo mostrará la línea final (recuento de fotogramas final).

Timothy Zorn
fuente
2

para construir sobre la respuesta de Stu. así es como encontré la velocidad de fotogramas de un video desde mi teléfono móvil. Ejecuté el siguiente comando por un tiempo. Dejé que el recuento de cuadros llegara a aproximadamente ~ 10,000 antes de impacientarme y presionar ^ C:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

luego, tomé dos piezas de información de esa línea que comienza con "frame =", el número de cuadros, 7989, y el tiempo, 00: 04: 26.30. Primero debe convertir el tiempo en segundos y luego dividir el número de fotogramas por segundos para obtener "fotogramas por segundo". "fotogramas por segundo" es su velocidad de fotogramas.

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

la velocidad de fotogramas de mi video es de 30 fps.

margarita
fuente
2

La única precisión que he podido hacer es la siguiente:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

Para asegurarse de que esto funcione con video:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Lloyd Moore
fuente
Voté tu respuesta, pero eso solo funcionará si el video no contiene audio. Si lo contiene, este funcionará:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

Lo siento por la respuesta necro, pero tal vez necesite esto (ya que no encontré una solución para las versiones recientes de ffmpeg.

Con ffmpeg 3.3.4 encontré uno que puede encontrar con lo siguiente:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

Al final, dará salida al recuento de cuadros. Me funcionó en videos con audio. Sin embargo, da dos veces una línea "nb_frames", pero la primera línea fue el recuento de cuadros real en los videos que probé.

acidrums4
fuente
Gracias @ acidrums4. Verificado que este método funciona con la última versión de github que construí hoy.
Paul J
1

Utilizo php_ffmpeg y luego puedo obtener todos los tiempos y todos los fotogramas de una película. Como a continuación

$input_file='/home/strone/workspace/play/CI/abc.rmvb';
$ffmpegObj = new ffmpeg_movie($input_file);
echo $ffmpegObj->getDuration();
    echo $ffmpegObj->getFrameCount();

Y luego el detalle está en la página.

http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

xingyue
fuente
1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Gerard Wensink
fuente
La velocidad de fotogramas se calcula normalmente a partir de dos parámetros. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Redondeado por ffmpeg a: 23.98 Duración = horas * 3600 + minutos * 60 + segundos.resto = 8177,91 Mientras que el parámetro de duración = 8177.794625 Pero marcos = 24000/1001 * 8177.794625 = 196071 da el número exacto de fotogramas. (En serio).
Gerard Wensink
0

linux

ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null

rubí

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
Yaroslav Malyk
fuente