Tengo un gran conjunto de archivos jpg que quiero convertir en un video sin pérdida (o, al menos, muy cerca de sin pérdida, siempre que el tiempo de codificación no sea mucho más alto).
Ingenuamente, pensaría que debería haber algún códec que pueda almacenar cada fotograma jpg individual tal cual (sin recompresión), y tal vez lograr una buena compresión reemplazando algunos de los fotogramas solo con la información en el delta del fotograma anterior. En mi caso hay muchas secuencias de fotogramas que son idénticos entre sí, o que tienen una pequeña diferencia entre ellos.
¿Hay algún códec y configuración adecuada para ffmpeg que pueda lograr esto?
Simplemente puede mezclar las imágenes JPG para hacer un video:
ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv
Tenga en cuenta que si omite , se aplicará -framerate
un valor predeterminado de a la entrada.-framerate 25
Puede usar jpegtran
para realizar una optimización sin pérdidas en cada cuadro, lo que puede proporcionar ahorros significativos en el tamaño del archivo:
mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done
Ahora mux con ffmpeg
como se muestra arriba.
El framehash muxer se puede usar para comparar el hash único de cada cuadro para garantizar que el resultado sea realmente sin pérdidas:
$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
En los ejemplos anteriores, cada marco asociado para la entrada y la salida comparten el mismo hash, lo que garantiza que los marcos sean idénticos y que la salida no tenga pérdidas.
framemd5
se supone que deben lograr los dos comandos más allá de simplemente enumerar los hash? ¿Cómo obtendría compresión adicional cuando se identifican fotogramas idénticos?Esto generará un video H.264 sin pérdidas donde los cuadros usarán información de otros cuadros
ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4
Explicación de opciones:
-f image2
- le dice a ffmpeg que seleccione un grupo de imágenes-r 30
- le dice a ffmpeg que codifique a 30 fotogramas (o imágenes) por segundo (cámbielo a la velocidad de fotogramas deseada)-i %09d.jpg
- le dice a ffmpeg que use las imágenes 000000000.jpg a 999999999.jpg como entrada. Cambie la cantidad 9
de %09d.jpg
ceros que tienen los nombres de su secuencia de imágenes. Si los nombres de sus archivos son, por ejemplo, img0001.jpg, esto se expresaría como img%04d.jpg-vcodec libx264
- le dice a ffmpeg que genere un archivo compatible con H.264-profile:v high444
- le dice a libx264 que use el perfil High 4:4:4 Predictive Lossless, lo que permite la codificación sin pérdidas-refs 16
- le dice a libx264 que tenga 16 imágenes almacenadas en un búfer, para que puedan ser referenciadas por otras imágenes en el video-crf 0
- le dice a libx264 que realice una codificación sin pérdidas-preset ultrafast
- le dice a libx264 que priorice la velocidad de codificación sobre el tamaño del archivo de salidaa.mp4
- le dice a ffmpeg que guarde la salida en un archivo MP4 llamado a.mp4. Cambie esto al nombre de archivo y formato que desea usar-f image2
es superfluo aquí. El demuxer del archivo de imagen debe usarse -framerate
en lugar de -r
. libx264 elegirá automáticamente el apropiado -profile
para sin pérdidas, y -preset
se encargará de -refs
.-refs 5
como MAYOR, a menos que sepa que su contenido tiene imágenes idénticas separadas por varias otras, eso podría causar que x264 pierda la referencia antes de que llegue al duplicado. Más alto que ultrafast
hace poca diferencia en el modo sin pérdidas, aparte de la ganancia de ~10% de CABAC sobre CAVLC (por un alto costo de CPU a las tasas de bits requeridas para sin pérdidas). En serio, en algunos 720x480p60 de acción en vivo (salida desentrelazada), superfast
eran 28 GB, slower
eran 27 GB. Si el tiempo de codificación no importa, pero el tiempo de decodificación sí, asegúrese de evitar CABAC. Tal vez incluso -tune fastdecode
. El conteo moderado de referencias no debería doler.-preset placebo
obtener algunas fracciones de porcentaje adicionales.-vcodec libx265 -x265-params lossless=1
es la opción equivalente. (Pero en mi experiencia (= grabación de presentaciones de diapositivas de Powerpoint), no es necesariamente mejor, y es mucho más lento que h264) Estén atentos para el próximo año AV1 de AOMedia/NETVC1 de IETF/Daala de Xiph/cualquiera que sea su nombre para entonces ... el modo sin pérdidasPuede crear una avi
animación como una serie de png
imágenes ( no png
tiene pérdidas, por lo que la jpeg => png
conversión no debería degradar sus imágenes):
si tus imágenes tienen un nombreimg_0001.jpg
ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec png video.avi
donde "25" es la velocidad de fotogramas que desea en el video resultante. -start_number
no es necesario si es 1, pero es útil si su primer número de video no es 1.
Si desea codificar mjpeg
con la línea de comando de la más alta calidad es:
ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec mjpeg -qscale 1 video.avi
Y lo bueno de esto es que puedes volver a convertir el video en una serie de imágenes:
ffmpeg -i video.avi "img_series_%04d.png"
ffmpeg -i video.avi "img_series_%04d.jpg"
etc...
Para ampliar la respuesta de LordNeckbeard, sí, simplemente mux los datos JPEG en una transmisión de video MJPEG. Esa será la representación más pequeña de la secuencia exacta de imágenes de salida, aunque MJPEG es un códec terriblemente ineficiente según los estándares actuales. (sin redundancia temporal, ni siquiera intrapredicción.
Puede hacer un video MJPEG de velocidad de fotogramas variable para aprovechar las imágenes duplicadas en su entrada.
ffmpeg -framerate 30 -i input%03d.jpg -vf mpdecimate -codec copy output.mkv # doesn't work.
Hrm, esto no va a funcionar, ya que mpdecimate no funcionará en datos comprimidos, y no podemos dejar que ffmpeg decodifique y luego vuelva a jpeg los datos de imagen sin pérdida y costo de CPU.
¿Tal vez si reemplazara los archivos de origen jpg duplicados con archivos vacíos con ese número de secuencia, o algo así?
Dado que esta pregunta ni siquiera es reciente, no me tomaré el tiempo para averiguar cómo hacerlo a menos que alguien responda para preguntar cómo. Pero dado que MJPEG puede ir a un contenedor mkv, estoy seguro de que es posible tener un archivo que no duplique los datos jpeg para cuadros repetidos, sino que simplemente no tenga un cuadro de salida para decodificar hasta que la secuencia de duplicados sea sobre.
Ah, aquí hay una idea:
ffmpeg -framerate blah -input blah -vf mpdecimate -f mkvtimestamp_v2 mpdecimate.timestamps
Luego elimine (o mueva a un lado) todos los jpegs para los marcos que mpdecimate quiere eliminar (¿probablemente tiene algunas opciones de registro? O -vf showinfo, y analice eso, y mueva o enlace fijo solo los marcos que aparecen en su salida, dejando atrás los JPEG caídos?). mux eso a un MJPEG.mkv, luego haga algo con mkvmerge para reemplazar las marcas de tiempo del marco en eso con las marcas de tiempo de mpdecimate.timestamps
.
Si estuviera codificando, en lugar de simplemente convertir datos jpeg en MJPEG, esto sería MUCHO más fácil, ya que solo usaría mi primer comando con mpdecimate y cualquier códec que no sea copy
, y simplemente funcionaría (tm).
No he probado nada de esto, ya que esta era una vieja pregunta. También la razón por la que no he llenado los vacíos de cómo filtrar realmente su directorio de jpegs en función de la salida de mpdecimate, o cómo usar realmente el flujo de marca de tiempo.
amigo de george
amigo de george
pedro cordes