ffmpeg duplicates

ffmpeg-elimina cuadros secuencialmente duplicados



duplicates (2)

También tuve este problema y la excelente respuesta de Gyan anterior me ayudó a comenzar, pero el resultado fue un audio desincronizado, así que tuve que explorar más opciones:

mpdecimate vs decimate filtros

  • mpdecimate es la recomendación estándar que encontré en todo SO e internet, pero no creo que deba ser la primera opción
    • utiliza heurísticas por lo que puede y saltará algunos marcos duplicados
    • puede ajustar la detección con el parámetro frac , pero es un trabajo adicional que puede evitar si puede
    • en realidad no se supone que funcione con el contenedor mp4 ( source ), pero estaba usando mkv por lo que esta limitación no se aplicó a mi caso, pero es bueno saberlo
  • decimate elimina cuadros con precisión, pero es útil solo para duplicados que ocurren periódicamente

velocidad de fotogramas detectada vs real

  • para que tenga un archivo multimedia con cuadros duplicados, es una buena idea asegurarse de que la velocidad de cuadros detectada coincida con la real
  • ffprobe in.mkv emitirá el FPS detectado; puede verse así

    Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1920x1080, SAR 1:1 DAR 16:9, 25 fps , 25 tbr, 1k tbn, 50 tbc (default)

  • la velocidad de fotogramas real se puede averiguar si abre el contenido multimedia in.mkv en un reproductor multimedia que le permite pasar un fotograma a la vez; luego cuente los pasos necesarios para avanzar el tiempo de reproducción durante 1 segundo, en mi caso fue de 30 fps

  • No fue una gran sorpresa para mí, porque cada sexto fotograma era duplicado (5 buenos fotogramas y 1 duplicado), así que después de 25 buenos fotogramas también había 5 duplicados.

¿Qué es N/FRAME_RATE/TB

  • excepto el uso de la variable FRAME_RATE , la N/FRAME_RATE/TB es igual al siguiente ejemplo de la documentación de ffmpeg ( source )

    Establecer tasa fija de 25 cuadros por segundo:
    setpts=N/(25*TB)

  • la matemática subyacente se explica perfectamente en ¿Qué es la escala de tiempo, la base de tiempo o la marca de tiempo del video en ffmpeg?

    • básicamente calcula la marca de tiempo para cada fotograma y la multiplica por TB base de tiempo para mejorar la precisión

Variable FRAME_RATE vs valor FPS literal (por ejemplo, 25)

  • Por eso es importante conocer su FPS detectado y real
  • Si el FPS detectado coincide con su FPS real (p. ej., ambos son 30 fps ), puede usar la variable FRAME_RATE en N/FRAME_RATE/TB
  • pero si el FPS detectado difiere del que tiene que calcular el FRAME_RATE por su cuenta
    • en mi caso, mi FPS real fue de 30 cuadros por segundo y eliminé cada 6º cuadro, por lo que el FPS objetivo es de 25, lo que lleva a N/25/TB
      • si usé FRAME_RATE (y en realidad lo intenté) tomaría los fps detectados incorrectamente de 25 cuadros, es decir, FRAME_RATE=25 , ejecutarlo a través del filtro mpdecimate que eliminaría cada 6 cuadros y se actualizaría a FRAME_RATE=20.833 por lo que N/FRAME_RATE/TB sería en realidad N/20.833/TB cual es completamente incorrecto

usar o no usar setpts

  • así que el filtro setpts ya se hizo bastante complicado, especialmente debido al desorden de FPS que pueden crear los cuadros duplicados
  • la buena noticia es que puede que no necesite el filtro setpts en absoluto
  • Esto es lo que usé con buenos resultados.

    ffmpeg -i in.mkv -vf mpdecimate out.mkv

    ffmpeg -i in.mkv -vf decimate =cycle=6, setpts =N/25/TB out.mkv

  • Pero lo siguiente me dio audio desincronizado.

    ffmpeg -i in.mkv -vf mpdecimate , setpts =N/FRAME_RATE/TB out.mkv

    ffmpeg -i in.mkv -vf mpdecimate , setpts =N/25/TB out.mkv

    ffmpeg -i in.mkv -vf decimate =cycle=6 out.mkv

  • como ves

nota sobre asetpts

  • hace el mismo trabajo que setpts pero para audio
  • realmente no corrigió el audio desync para mí, pero quieres usarlo así: -af asetpts =N/SAMPLE_RATE/TB
  • tal vez SAMPLE_RATE ajustar SAMPLE_RATE acuerdo con la proporción de fotogramas duplicados eliminados, pero me parece un trabajo adicional innecesario, especialmente cuando mi video tenía el audio sincronizado al principio, por lo que es mejor usar comandos que lo mantengan de esa manera en lugar de arreglarlo luego

tl; dr

Si el comando generalmente recomendado ffmpeg -i in.mkv -vf mpdecimate , setpts =N/FRAME_RATE/TB out.mkv no funciona, intente esto:

ffmpeg -i in.mkv -vf mpdecimate out.mkv

o

ffmpeg -i in.mkv -vf decimate =cycle=6, setpts =N/25/TB out.mkv

( cycle=6 porque cada sexto fotograma es duplicado y N/25/TB porque después de eliminar los duplicados, el video tendrá 25 fps (evite la variable FRAME_RATE ); ajústelo a su caso de uso)

¿Hay alguna forma de detectar fotogramas duplicados dentro del video usando ffmpeg ?

-vf indicador -vf con select=gt(scene/,0.xxx) para el cambio de escena. Pero, no funcionó para mi caso.


Utilice el filtro mpdecimate , cuyo propósito es "Eliminar fotogramas que no difieran mucho del fotograma anterior para reducir la velocidad de fotogramas".

  • Esto generará una lectura de consola que muestra los cuadros que el filtro cree que son duplicados.

    ffmpeg -i input.mp4 -vf mpdecimate -loglevel debug -f null -

  • Para generar un video con los duplicados eliminados.

    ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mp4

setpts expresión de filtro de setpts genera marcas de tiempo suaves para un video a FRAME_RATE fps. Vea una explicación de las marcas de tiempo en ¿Qué es la escala de tiempo, la base de tiempo o la marca de tiempo de video en ffmpeg?