Muxing multiple JPEG into a JXL animation

668 views Asked by At

Using ffmpeg I can mux multiple JPEG into a M-JPEG container without any loss since it is a just a plain bitstream copy:

ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mjpeg

Recently linux distributions started to offer JPEG-XL command line tools. I can now recode (lossless recompression) of JPEG into JXL:

% file input.jpg
input.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 1016x708, components 3
% cjxl input.jpg output.jxl
% djxl output.jxl output.jpg
% md5sum input.jpg output.jpg
bea9e9c74e3580f6196ba9ac21509652  input.jpg
bea9e9c74e3580f6196ba9ac21509652  output.jpg

However I fail to understand how to create a JXL animation (more than one JPEG) ?

Eg:

% ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.jxl
[...]
[image2 @ 0x55c22e680040] The specified filename 'output.jxl' does not contain an image sequence pattern or a pattern is invalid.
[image2 @ 0x55c22e680040] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image.
[image2 @ 0x55c22e680040] Cannot write more than one file with the same name. Are you missing the -update option or a sequence pattern?
av_interleaved_write_frame(): Invalid argument
frame=    2 fps=0.0 q=-1.0 Lsize=N/A time=00:00:00.06 bitrate=N/A speed= 223x
video:224kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Conversion failed!

Or:

% cjxl input*.jpg output.jxl
Unknown argument: input002.jpg
Use 'cjxl -h' for more information
1

There are 1 answers

1
Mikael Öhman On

Short answer: I don't the ability to do this is exposed in the existing tools (yet), but the code library code itself looks promising (but requires making a custom utility or possible a significant addition to the jcxl utility).

I would consider opening a feature request/issue on this.


As of writing this answer the jxl reference implementation for cjxl the real work starts with the entry point EncodeImageJXL(params, ppf, jpeg_bytes, &compressed); where jpeg_bytes is optional (may be nullptr, and only represents a single image) and otherwise the image data (which could contain multiple frames) is otherwise part of ppf.

After some initial setup this function splits logic based on this optional jpeg_bytes where it will either use the where it will either use the provided single jpeg bytes directly via JxlEncoderAddJPEGFrame or loop over each frame in ppf.frames and call JxlEncoderAddImageFrame for each frame decompressed pixel data.

There is also a fair number setup and settings that differ between these code paths, and I have a hard time differentiating what what is necessarily related to animation of what is just a result of doing full compression rather than just re-compressing the jpeg data.

Unfortunately, there is currently no way to use cjxl to even select multiple input files for cjxl right now, and I don't think ffmpeg exposes a way to select the necessary JxlEncoderAddJPEGFrame encoding at all. But the code does suggest to me that it should be possible by picking out the necessary setup from each code path and calling JxlEncoderAddJPEGFrame for each jpeg file data. Perhaps this could be made part of cjxl; most of the work would be to make it safe (checking that all images are jpegs, checking similar sizes, adding options for framerate etc.).

I could be missing some fundamental limitation in the jxl bytestream which means this type of lossless re-compression isn't supported, but seeing as there isn't any inter-prediction I'm hopeful that this is supported.