Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How can I create an uncompressed AVI from a series of 1000's of PNG images using FFMPEG?

I used this command to convert an input.avi file to a series of PNG frames:

ffmpeg -y -i input.avi  -an -vcodec png  -s 1024x768 pic%d.png`

Now I need to know how to make an uncompressed AVI video from all those PNG frames. I tried this:

ffmpeg -i pic%d.png -y -f avi -b 1150 -s 1024x768 -r 29.97 -g 12 -qmin 3 -qmax 13 -ab 224 -ar 44100 -ac 2 test.avi

But the resulting video loses a lot of quality relative to the original AVI.

share|improve this question

migrated from stackoverflow.com Oct 17 '11 at 13:43

This question came from our site for professional and enthusiast programmers.

2 Answers 2

There are several ways to get an "uncompressed" AVI out of ffmpeg, but I suspect you actually mean "lossless." Both terms have a fair bit of wiggle room in their definitions, as you will see.

I'm going to anchor this discussion with the 720p HD version of Big Buck Bunny, since it's a freely-available video we can all test with and get results we can compare.

The raw data rate of 1280×720p video at 24 fps is very nearly equal to that of your 1024×768 at 29.97 fps goal. The delta is only about 7%, so the numbers you'd get with your frame size and frame rate should be close to my numbers below.

Fully Uncompressed

If your definition of "uncompressed" is the form the video is in right before it's turned to photons by a digital display, the closest I see in the ffmpeg -codecs list are -vcodec r210, r10k, v410, v308, ayuv and v408. These are all substantially the same thing, differing only in color depth, color space, and alpha channel support.

  • R210 and R10K are 4:4:4 RGB at 10 bits per component (bpc), so they both require about 708 Mbit/s for 720p in my testing. (That's about ⅓ TB per hour, friends!)

    These codecs both pack the 3×10 bit color components per pixel into a 32-bit value for ease of manipulation by computers, which like power-of-2 sizes. The only difference between these codecs is which end of the 32-bit word the two unused bits are on. This trivial difference is doubtless because they come from competing companies, Blackmagic Design and AJA Video Systems, respectively.

    Although these are trivial codecs, you will probably have to download the Blackmagic and/or AJA codecs to play files using them on your computer. Both companies will let you download their codecs without having bought their hardware first, since they know you may be dealing with files produced by customers who do have some of their hardware.

  • V410 is essentially just the YUV version of R210/R10K; their data rates are identical. This codec may nevertheless encode faster, because ffmpeg is more likely to have an accelerated color space conversion path between your input frames' color space and this color space.

    I cannot recommend this codec, however, since I was unable to get the resulting file to play in any software I tried, even with the AJA and Blackmagic codecs installed.

  • V308 is the 8 bpc variant of V410, so it comes to 518 Mbit/s in my testing. As with V410, I was unable to get these files to play back in normal video player software.

  • AYUV and V408 are essentially the same thing as V308, except that they include an alpha channel, whether it is needed or not! If your video doesn't use transparency, this means you pay the size penalty of the 10 bpc R210/R10K codecs above without getting the benefit of the deeper color space.

    AYUV does have one virtue: it is a "native" codec in Windows Media, so it doesn't require special software to play.

    V408 is supposed to be native to QuickTime in the same way, but the V408 file wouldn't play in either QuickTime 7 or 10 on my Mac.

So, putting all this together, if your PNGs are named frame0001.png and so forth:

$ ffmpeg -i frame%04d.png -vcodec r10k output.mov
  ...or...                -vcodec r210 output.mov
  ...or...                -vcodec v410 output.mov
  ...or...                -vcodec v408 output.mov
  ...or...                -vcodec v308 output.mov
  ...or...                -vcodec ayuv output.avi

Notice that I have specified AVI in the case of AYUV, since it's pretty much a Windows-only codec. The others may work in either QuickTime or AVI, depending on which codecs are on your machine. If one container format doesn't work, try the other.

The above commands — and those below, too — assume your input frames are already the same size as you want for your output video. If not, add something like -s 1280x720 to the command, before the output file name.

Compressed RGB, But Also Lossless

If, as I suspect, you actually mean "lossless" instead of "uncompressed," a much better choice than any of the above is Apple QuickTime Animation, via -vcodec qtrle

I know you said you wanted an AVI, but the fact is that you're probably going to have to install a codec on a Windows machine to read any of the AVI-based file formats mentioned here, whereas with QuickTime there's a chance the video app of your choice already knows how to open a QuickTime Animation file. (The AYUV codec above is the lone exception I'm aware of, but its data rate is awfully high, just to get the benefit of AVI.)

ffmpeg will stuff qtrle into an AVI container for you, but the result may not be very widely compatible. In my testing, QuickTime Player will gripe a bit about such a file, but it does then play it. Oddly, though, VLC won't play it, even though it's based in part on ffmpeg. I'd stick to QT containers for this codec.

The QuickTime Animation codec uses a trivial RLE scheme, so for simple animations, it should do about as well as Huffyuv below. The more colors in each frame, the more it will approach the bit rate of the fully uncompressed options above. In my testing with Big Buck Bunny, I was able to get ffmpeg to give me a 165 Mbit/s file in RGB 4:4:4 mode, via -pix_fmt rgb24.

Although this format is compressed, it will give identical output pixel values to your PNG input files, for the same reason that PNG's lossless compression doesn't affect pixel values.

The ffmpeg QuickTime Animation implementation also supports -pix_fmt argb, which gets you 4:4:4:4 RGB, meaning it has an alpha channel. In a very rough sort of way, it is the QuickTime equivalent to -vcodec ayuv, mentioned above. Because of the lossless compression, though, it comes to only 214 Mbit/s, less than ⅓ the data rate of AYUV with zero loss in quality or features.

There are variants of QuickTime Animation with fewer than 24 bits per pixel, but they're best used for progressively simpler animation styles. ffmpeg appears to support only one of the other formats defined by the spec, -pix_fmt rgb555be, meaning 15 bpp big-endian RGB. It's tolerable for some video, and is fine for most screencast captures and simple animations. If you can accept the color space decimation, you may find its 122 Mbit/s data rate appealing.

Putting all this together:

$ ffmpeg -i frame%04d.png -vcodec qtrle -pix_fmt rgb24    output.mov
  ...or...                              -pix_fmt argb     output.mov
  ...or...                              -pix_fmt rgb555be output.mov

Effectively Lossless: The YUV Trick

Now, the thing about RGB and 4:4:4 YUV is that these encodings are very easy for computers to process, but they ignore a fact about human vision, which is that our eyes are more sensitive to black and white differences than color differences.

Video storage and delivery systems therefore almost always use fewer bits per pixel for color information than for luminance information. The most common schemes are 4:2:0 and 4:2:2.

The data rate of 4:2:0 YUV is just 33% higher than for black and white (Y only) uncompressed video, or half the data rate of 4:4:4 RGB or YUV.

4:2:2 is a kind of halfway point between 4:2:0 and 4:4:4. It is twice the data rate of Y-only video, or ⅔ the data rate of 4:4:4.

(You also sometimes see 4:1:1, as in the old DV camera standard. 4:1:1 has the same uncompressed data rate as 4:2:0, but the color information is arranged differently.)

The point of all this is that if you're starting with a 4:2:0 H.264 file, re-encoding it to 4:4:4 uncompressed RGB buys you absolutely nothing over 4:2:0 losslessly-compressed YUV. This is true even if you know your workflow is otherwise 4:4:4 RGB, since it's a trivial conversion; video hardware and software do such conversions on the fly routinely.

You really only need 4:4:4 when you're pixel peeping or you're doing pixel-level color changes on the video, and need to preserve exact pixel values. Visual effects (VFX) work is easier to do with a 4:4:4 pixel format, for example, so high-end VFX houses are often willing to tolerate the higher data rates it requires.

Effectively Lossless: Codec Choices

Once you open yourself up to YUV codecs with color decimation, your options open up, too. ffmpeg has many effectively lossless codecs.

The most widely compatible option is Huffyuv. You get this via -vcodec huffyuv.

The original Windows Huffyuv codec only supports two pixel formats: RGB24 and YUV 4:2:2. (Actually, it supports two flavors of YUV 4:2:2, differing only in the order of the bytes on disk.)

Older versions of the FFmpeg Huffyuv codec did not include RGB24 support, so if you try it and FFmpeg tells you it is going to use the yuv422p pixel format, you need to upgrade.

FFmpeg also has a Huffyuv variant codec called FFVHuff, which supports YUV 4:2:0. This variant isn't compatible with the Windows DirectShow Huffyuv codec, but it should open in any software based on libavcodec, such as VLC.

  • RGB24 — RGB 4:4:4 is essentially the same thing as QuickTime Animation's RGB24 color space option. The two codecs will differ somewhat in compression for a given file, but they will usually be close.

    It is also essentially the same thing as the YUV 4:4:4 mode used by the V308 option above. The color space difference makes no practical difference, since the color space conversion is easy to do in real time.

    Due to Huffyuv's lossless compression, I was able to get a test video to compress to about 251 Mbit/s in RGB24 mode, with identical visual quality to what you'd get from V308 or AYUV. If AVI is an absolute must for you, installing the Huffyuv codec is probably less painful than paying the 3× data rate cost of AYUV.

  • YUV 4:2:2 — This mode is far more practical for video than RGB24, which is doubtless why the ffmpeg developers chose to implement it first. As you'd expect from the theoretical ⅔ reduction discussed above, my test file encoded to 173 Mbit/s. That's pretty much exactly ⅔, if you take into account the fact that the audio track was unchanged between these two tests.

  • YUV 4:2:0 — This option decimates the color information more than 4:2:2 does, dropping the data rate to 133 Mbit/s in my testing.

Putting all this together:

$ ffmpeg -i frame%04d.png -vcodec huffyuv -pix_fmt rgb24   output.avi
  ...or...                                -pix_fmt yuv422p output.avi
  ...or...                -vcodec ffvhuff -pix_fmt yuv420p output.avi

Although the ffvhuff codec defaults to 4:2:0 as I write this, and indeed only supports that pixel format in the release version I'm using, this is changing, so you should include the flag in case this default changes.

ffmpeg also supports decode-only mode for Lagarith and encode-only mode for Lossless JPEG. These two codecs are actually somewhat similar, and should give files a bit smaller than Huffyuv with the same quality. If the ffmpeg developers ever add Lagarith encoding, it would be a strong alternative to Huffyuv.

I can't recommend Lossless JPEG, though, because the support for this format isn't very good across the industry. There is a commercial Windows codec, but I don't know if it can decode the files ffmpeg creates.

Perceptually Lossless: Or, You Can Probably Get Away With Some Loss

Then there are the codecs that are perceptually lossless. Unless you're pixel peeping, you almost certainly cannot tell that these give different visual results than the previous two groups. By giving up on the idea of absolutely zero change between the video capture sensor and the display device, you buy considerable savings:

  • Apple ProRes: -vcodec prores or -vcodec prores_ks — ProRes is a profile-based codec, meaning that there are several variants, each with a different quality vs. space tradeoff:

    • ProRes 4444 encodes our test video using only 114 Mbit/s, yet is VFX quality. There are currently three different prores* codecs in FFmpeg, but only prores_ks supports ProRes 4444, as I write this, via the -profile:v 4444 option.

    • ProRes 422 saves even more space, needing only 84 Mbit/s to give a result you can tell from ProRes 4444 only by pixel-peeping. Unless you need the alpha channel offered by ProRes 4444, there's probably no reason to insist on ProRes 4444.

      All three of the ProRes encoders in FFmpeg support the ProRes 422 profile, so the simplest option is to use -vcodec prores, rather than -vcodec prores_ks -profile hq, or depend on the auto-profile feature of prores_ks to do the right thing.

    There are even more parsimonious ProRes profiles, but they're meant for either SD video or as proxies for full-res files.

    The main problem with ProRes is that it doesn't yet have wide support outside the Apple and pro video worlds.

  • Low-loss MJPEG: -vcodec mjpeg -qscale:v 1 — This is far more common than lossless JPEG, and so it's much easier to get support for it. Expect pretty wide variability in data rates from this codec. A test I just made here gave me 25 Mbit/s for 720p video. That's high enough compression to make me nervous about lossiness, but it looked pretty good to me. Based on data rate alone, I'd say it's probably on par quality-wise to 12 Mbit/s MPEG-2 or 6 Mbit/s H.264.

Putting all this together:

$ ffmpeg -i frame%04d.png -vcodec prores_ks -profile:v 4444 output.mov
  ...or...                -vcodec prores_ks -profile:v hq   output.mov
  ...or...                -vcodec prores                    output.mov
  ...or...                -vcodec mjpeg -qscale:v 1         output.avi

Bottom line on these methods is that unless you're doing something very demanding, "good enough" really is good enough.

share|improve this answer

I think ffmpeg actually does support converting to uncompressed video.
I used ffmpeg -i input.mp4 -vcodec rawvideo out.avi and the resulting .avi was roughly the right filesize. Windows media player didn't seem to be able to play it correctly but it could be read by VirtualDub and I did not see any loss in picture quality.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.