32

I'm using ffmpeg to take a mjpeg feed from an IP camera and convert it into a series of still jpeg images. Here's the command I'm using:

ffmpeg -i http://xxx:xxx@xx.xx.xx.xx/vid.mjpg -f image2 -vcodec mjpeg %05d.jpg

Does anyone know a way to specify the level of jpg compression when using ffmpeg to create stills?

4 Answers 4

47

Here's what ended up doing the trick for me:

ffmpeg -i http://xx.xx/mjpg/video.mjpg -q:v 1 %05d.jpg

The -q:v 1 was the ticket. It sets the quality of the video encoder, where the -q means quality and the :v means video. Values range from 1 to 31, where lower means better.

4
  • 4
    I don't know if this was available years ago but if you want the source JPEG images unmodified from MJPEG, the answer is here: ffmpeg.org/ffmpeg-bitstream-filters.html#mjpeg2jpeg ---- In short: -c:v copy -bsf:v mjpeg2jpeg instead of q:v 1.
    – juanitogan
    Dec 24, 2016 at 11:51
  • 3
    Does anyone know what default value it uses? Oct 10, 2017 at 16:35
  • 1
    @JayR.Wren I did some tests and in my case it seems to start out low (good) and after a few seconds rises to 24.8 (bad). I don't know why. ffmpegs shows the current quality as q. Here it is 24.8 for example frame= 64 fps=5.0 q=24.8 Lsize=N/A time=00:00:16.00 bitrate=N/A dup=10 drop=299 speed=1.25x May 2, 2019 at 16:26
  • The default value is variable. It starts at 7, but quickly moves towards 1 or 31, based on a few other settings. My build of ffmpeg has a default output avg bitrate of 200000 (wow), so it quickly moves down to q:v 1 (opposite to @JayR.Wren). If you instead specify -b:v 10000 (avg bitrate target 10k) you'd see it quickly move up towards q:v 31. That said, 7 seems to be the starting point of the variable rate, and to me also seems like a sane default, before tweaking up or down from there (I personally find myself using values from 3 to 9).
    – jameslol
    Mar 31, 2021 at 3:09
6

$ ffmpeg -r 1/4 -i %03d.jpg -b 5000 -vcodec mjpeg -qscale 1 5000.avi

OR

$ ffmpeg -r 1/4 -i %03d.jpg -vcodec copy -qscale 1 copy.avi

Reference:

r       delay between next jpg, results 4 second
b       bitrate
vcodec  use jpeg encode
qscale  quality ratio
2
  • does qscale "compete" with the bitrate specifier, I wonder?
    – rogerdpack
    Jan 19, 2013 at 17:45
  • 2
    Isn't this opposite of what is being asked? This looks like jpeg to mjpeg. mjpeg to jpeg is the ask.
    – juanitogan
    Dec 22, 2016 at 23:35
4

You could try to export into PPM and use some other tool to convert into JPEG.

I looked into ffmpeg/libavcodec/mjpeg.c. I believe the quality is set to a fixed value.

Also you seem to convert a MJPEG video into JPEG still frames. I think in this case the code in ffmpeg/libavcodec/mjpeg2jpeg_bsf.c runs and the data isn't recoded. So the image quality wouldn't improve anyway.

This is the quantization table definition, I didn't see any reference to *val_?c where the values were scaled before use.

/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
const uint8_t ff_mjpeg_bits_dc_luminance[17] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
const uint8_t ff_mjpeg_val_dc[12] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

const uint8_t ff_mjpeg_bits_dc_chrominance[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };

const uint8_t ff_mjpeg_bits_ac_luminance[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
const uint8_t ff_mjpeg_val_ac_luminance[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
4
  • I'm not familiar with PPM, what is that?
    – weotch
    Aug 3, 2011 at 22:28
  • Also, the images look better when I access the camera from the browser compared to the jpgs I'm creating. That's why I was thinking some compression was occurring.
    – weotch
    Aug 3, 2011 at 22:31
  • PPM is simplest color image format one can imagine. Its just a header like "P6 640 480 255\n" and then the raw data. I just looked. Maybe it actually can't output this format. The only other option then would be -vc rawvideo. Did you try -quality?
    – whoplisp
    Aug 3, 2011 at 22:41
  • 1
    -vcodec ppm is needed to export ppm
    – OrangeDog
    Jan 10, 2012 at 14:08
1

Simpliest way I found

Explode video file in .png (lossless) then convert them in jpeg:

ffmpeg -i inputfile.avi image-%07d.png

(without option, this will extract all frames.)

I prefer using png compression even if ffmpeg is able to produce .ppm files (not compressed). Because using PPM will require a lot of disk space and won't be quicker (due to disk write time, of course not tested with SSD;).

Then (using netpbm tools)

JPEGQUALITY=95
for file in *.png;do
    echo -n $file...
    pngtopnm $file | pnmtojpeg -q $JPEGQUALITY >${file%.png}.jpg
    echo -e \\e[6Djpg\\e[K.
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.