Saltar al contenido

Elimina fotogramas duplicados secuencialmente cuando usas FFmpeg

Solución:

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 la consola que muestra qué fotogramas 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
    

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

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 diezmar 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ística, por lo que puede omitir algunos fotogramas duplicados
    • puedes modificar la detección con frac parámetro, pero es un trabajo adicional que quizás desee evitar si puede
    • realmente no se supone que funcione con mp4 contenedor (fuente), pero estaba usando mkv así que esta limitación no se aplicó en mi caso, pero es bueno estar al tanto
  • decimate Elimina marcos con precisión, pero es útil solo para duplicados que ocurren periódicamente.

velocidad de fotogramas detectada frente a real

  • para que tenga un archivo multimedia con fotogramas duplicados, es una buena idea asegurarse de que la velocidad de fotogramas detectada coincida con la real
  • ffprobe in.mkv generará 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 medio in.mkv en un reproductor multimedia que le permite avanzar un fotograma a la vez; luego cuente los pasos necesarios para avanzar el tiempo de reproducción durante 1 segundo, en mi caso fue 30 fps

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

que es N/FRAME_RATE/TB

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

    Establezca una velocidad fija de 25 fotogramas por segundo:
    setpts=N/(25*TB)

  • las matemáticas detrás de esto se explican 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 la base de tiempo. TB para mejorar la precisión

FRAME_RATE variable vs valor literal de FPS (por ejemplo, 25)

  • por eso es importante conocer su FPS detectado y real
  • si el FPS detectado coincide con su FPS real (por ejemplo, ambos son 30 fps) puedes usar felizmente FRAME_RATE variable en N/FRAME_RATE/TB
  • pero si el FPS detectado difiere de lo que tiene que calcular el FRAME_RATE por tu cuenta
    • en mi caso, mi FPS real fue 30 fotogramas por segundo y eliminé cada sexto fotograma, por lo que el FPS objetivo es 25 lo que lleva a N/25/TB
      • si yo usara FRAME_RATE (y de hecho lo intenté) tomaría los fps detectados incorrectamente de 25 marcos es decir FRAME_RATE=25, ejecutarlo mpdecimate filtro que eliminaría cada sexto fotograma y se actualizaría a FRAME_RATE=20.833 asi que N/FRAME_RATE/TB realmente sería N/20.833/TBque esta completamente mal

usar o no usar setpts

  • por lo que el filtro de setpts ya se volvió bastante complicado, especialmente debido al desorden de FPS que pueden crear los fotogramas duplicados
  • la buena noticia es que es posible que no necesite el filtro de configuración 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

    • mpdecimate y diezmar no funciona de la misma manera
    • mpdecimate funcionó mejor para mí sin el filtro de setpts
    • mientras diezma el filtro de setpts necesarios y, además, necesito evitar FRAME_RATE variable y uso N/25/TB en cambio, porque el FPS real no se detectó correctamente

nota sobre asetpts

  • hace el mismo trabajo que setpts pero para audio
  • Realmente no solucionó la desincronización del audio para mí, pero quieres usarlo de esta manera -af asetpts=N/SAMPLE_RATE/TB
  • tal vez se supone que debes ajustar el SAMPLE_RATE de acuerdo con la proporción de fotogramas duplicados eliminados, pero me parece un trabajo extra innecesario, especialmente cuando mi video tenía el audio sincronizado al principio, por lo que es mejor usar comandos que lo mantengan así en lugar de arreglarlo más tarde

tl; dr

Si el comando generalmente recomendado ffmpeg -i in.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mkv no funciona para ti, prueba 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 está duplicado y N/25/TB porque después de eliminar los duplicados el video tendrá 25 fps (evite el FRAME_RATE variable); ajustar para su caso de uso)

Aquí tienes las reseñas y calificaciones

Ten en cuenta mostrar este ensayo si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *