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
-
mpdecimatees 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 usandomkvpor lo que esta limitación no se aplicó a mi caso, pero es bueno saberlo
-
decimateelimina 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.mkvemitirá 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.mkven 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, laN/FRAME_RATE/TBes 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
TBbase de tiempo para mejorar la precisión
- básicamente calcula la marca de tiempo para cada fotograma y la multiplica por
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_RATEenN/FRAME_RATE/TB - pero si el FPS detectado difiere del que tiene que calcular el
FRAME_RATEpor 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 filtrompdecimateque eliminaría cada 6 cuadros y se actualizaría aFRAME_RATE=20.833por lo queN/FRAME_RATE/TBsería en realidadN/20.833/TBcual es completamente incorrecto
- si usé
- 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
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.mkvffmpeg -i in.mkv -vf decimate =cycle=6, setpts =N/25/TB out.mkvPero lo siguiente me dio audio desincronizado.
ffmpeg -i in.mkv -vf mpdecimate , setpts =N/FRAME_RATE/TB out.mkvffmpeg -i in.mkv -vf mpdecimate , setpts =N/25/TB out.mkvcomo ves
- mpdecimate y decimate no funciona de la misma manera
- mpdecimate funcionó mejor para mí sin filtros setpts
- Mientras setpts filtro de setpts necesario, setpts evitar la variable
FRAME_RATEy usarN/25/TBlugar porque el FPS real no se detectó correctamente
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_RATEajustarSAMPLE_RATEacuerdo 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?