How to create an uncompressed AVI from a series of 1000's of PNG images using FFMPEG
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 stated 1024×768 at 29.97 fps goal, so my results should be a pretty good guide to the data rates you can expect on your footage.
Automatic Listing of Available Options
The following POSIX command¹ gives you a list that mostly² matches what we discuss below:
$ ffmpeg -codecs 2> /dev/null | grep '^..EV..S ' | grep -vE 'bitmap|image'
You might want to run that command on your own machine to see what your build of FFmpeg will support. FFmpeg is rarely built with every possible encoder enabled.
Now let's discuss those options.
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 -c:v 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 -c:v r10k output.mov
...or... -c:v r210 output.mov
...or... -c:v v410 output.mov
...or... -c:v v408 output.mov
...or... -c:v v308 output.mov
...or... -c:v 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 -c:v 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 -c:v 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 -c:v 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. This is called chroma subsampling. The most common schemes are 4:2:0 and 4:2:2.
The data rate of 4:2:0 YUV is just 50% higher than for black and white (Y only) uncompressed video and ½ 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 and ⅔ 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 you 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.
Huffyuv
The most widely compatible option is Huffyuv. You get this via -c:v 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 -c:v huffyuv -pix_fmt rgb24 output.avi
...or... -pix_fmt yuv422p output.avi
...or... -c:v 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.
Ut Video
A more recent option in the same spirit as Huffyuv and FFVHuff is Ut Video. Like Huffyuv, there is a Windows video codec which means any Windows program that can play a movie can play videos using this codec with the codec installed. Unlike Huffyuv, there is also a Mac video codec as well, so you aren't restricted to software based on FFmpeg or libavcodec
to read these files on Macs.
This codec is very flexible in terms of color spaces, so I will just give a few examples of common color spaces:
4:4:4 RGB via
-f avi -c:v utvideo -pix_fmt rgb24
gives 178 Mbit/sec output4:4:4 YUV via
-f avi -c:v utvideo -pix_fmt yuv444p
gives 153 Mbit/sec output4:2:2 YUV via
-f avi -c:v utvideo -pix_fmt yuv422p
gives 123 Mbit/sec output4:2:0 YUV via
-f avi -c:v utvideo -pix_fmt yuv420p
gives 100 Mbit/sec output
I suspect 4:4:4 YUV does better than 4:4:4 RGB in this test despite these two being technically equivalent because the source video is 4:2:0 YUV, so arranging the data in YUV format allows for better lossless compression by grouping the partially-redundant U and V channels together in the file.
FFV1
Another interesting option in this space is FFmpeg's own FFV1
codec. This is mostly used as an archival codec rather than a playback or editing codec, but since so much software is either based on the libavcodec
library underpinning FFmpeg or can be lashed to libavcodec
via tools like ffdshow
, it may be useful to you anyway.
By default, ffmpeg
will preserve your input files' color space when using a flexible codec like FFV1, so that if you feed it one of the official Big Buck Bunny MP4 files, which use 4:2:0 YUV, that's what you'll get out unless you give a -pix_fmt
flag to ffmpeg
. This results in a 63 Mbit/s output file.
If you force FFV1 to use a 4:4:4 YUV color space with -pix_fmt yuv444p
, the file size only goes up to 86 Mbit/sec, but it's buying us nothing in this case since we're encoding from a 4:2:0 original. However, if you feed in a set of PNGs instead, as in the original question, the output file is likely to use the bgra
or bgr0
color space, which are just rearrangements of the argb
and rgb24
color spaces brought up above.
Lossless H.264
Another interesting alternative is Lossless H.264. This is pretty much an x264-only thing as of this writing, but those using FFmpeg on the encoding side are likely to be using other software that includes libx264
on the decoding side, too, such as VLC.
The simplest way to get such a file is:
$ ffmpeg -i frame%04d.png -c:v libx264 -qp 0 -f mp4 output.mp4
The -qp 0
flag is the key: higher values give lossy compression. (You can also give -crf 0
to get the same effect.)
As with FFV1, ffmpeg
will try to guess the best output color space given the input color space, so for comparison to the results above, I ran multiple encode passes on the Big Buck Bunny source file with different color spaces:
yuv444p: This is what
ffmpeg
chooses when you give it an RGB PNG stream, as in the original question, and results in a 44 Mbit/sec file with our test fileyuv422p: This is similar to the default color space for Huffyuv, but we get a 34 Mbit/sec file in this case, quite a savings!
yuv420p: This is the default for the Big Buck Bunny official MP4s I'm testing with, and results in a 29 Mbit/sec file.
Beware that you're trading a lot of compatibility to get such small file sizes. That's why I didn't even bother trying to stuff this into an AVI or MOV container. It's so closely tied to x264 that you might as well use its standard container type (MP4) instead. You could also use something like Matroska for this.
You can trade off some of that bit rate for a faster encoding time by adding -preset ultrafast
. That increased my test file's bit rate to 44 Mbit/s in YUV 4:2:2 mode, but encoded much faster, as promised. The docs claim that -preset veryslow
is also worthwhile, but it resulted in a much longer encode time while only saving a tiny bit of space; I can't recommend it.
Others
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 cannot recommend Lossless JPEG, though, since it doesn't enjoy wide decoding support.
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:
-c:v prores
or-c:v 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 onlyprores_ks
supports ProRes 4444, as I write this, via the-profile:v 4444
option.If you're wondering why you'd bother going with ProRes 4444 over Lossless H.264, it comes down to compatibility, decoding speed, predictability, and the alpha channel.
-
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.
ProRes 422 is a closer competitor to the Lossless H.264 option above, since neither supports an alpha channel. You'll want to tolerate the higher bit rate of ProRes if you need compatibility with Apple pro video apps, a lower CPU overhead for encoding and decoding, or predictable bit rates. The latter is important with hardware encoders, for example. On the other hand, if you can cope with the compatibility problems of Lossless H.264, you get the option of using the 4:2:0 color space, which isn't an option from any ProRes profile.
All three of the ProRes encoders in FFmpeg support the ProRes 422 profile, so the simplest option is to use
-c:v prores
, rather than-c:v prores_ks -profile hq
, or depend on the auto-profile feature ofprores_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.
-
-
Avid's DNxHD is a similar codec to ProRes, but isn't tied to the Apple pro video world. Avid offers freely-downloadable codecs for both Windows and Macintosh, and FFmpeg now supports it via
-c:v dnxhd
.Because DNxHD is a profile-based codec like ProRes, you choose the profile from the predefined set, and that tells the codec which frame size, frame rate, and bit rate to use. For the Big Buck Bunny test file, the
-b:v 60M
profile is most appropriate. Unsurprisingly, the resulting file is about 59 Mbit/s. -
Low-loss MJPEG:
-vcodec mjpeg -qscale:v 1
— This is far more common than lossless JPEG. In fact, this was once a quite common video editing codec, and it's still frequently used by things like networked streaming video cameras. All that history means it is easy to find software that supports 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 -c:v prores_ks -profile:v 4444 output.mov
...or... -c:v prores_ks -profile:v hq output.mov
...or... -c:v prores output.mov
...or... -c:v dnxhd -b:v 60M output.mov
...or... -c:v 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.
Footnotes and Digressions
The command should work as-given on Linux, macOS, the BSDs, and Unix. If you're on Windows, you can get a POSIX command line via Cygwin or WSL.
-
There are several reasons why the list produced by that command doesn't perfectly match the set of codecs I've chosen to discuss above:
-
The second
grep
is meant to filter out inappropriate encoders likebmp
which are not "video" codecs, despite being taggedV
in this list. While technically you could probably stuff many of these into a container like AVI, MP4, or MKV to get a single-file video, that file won't likely be readable by anything but a program based onffmpeg
orlibavcodec
.There are a few exceptions to this, such as that
-f avi -c:v ljpeg
gives something you could call "Lossless MJPEG," but as a rule, we're not interested in stuffing many still-image files into an A/V container here to make a movie. We want widely-recognized video codecs here, not semantic trickery. -
The command currently fails to filter out some inappropriate encoders such as GIF because they are not currently described in the
ffmpeg -codecs
output asbitmap
orimage
file formats.GIF is an interesting case: it supports multiple image frames in a single GIF file with timing information for motion playback, but for several reasons, it is entirely inappropriate to our discussion here.
A few of the options that are shown are obsolete or never really got much traction, such as
flashsv
,dirac
, andsnow
, so it's not worth discussing them above.Some of the options in that list are meant only for use in pipelines between
ffmpeg
instances or betweenffmpeg
and another program, such asrawvideo
andwrapped_avframe
, and so are inappropriate for our purposes here.Near the end of the discussion above, I judiciously expand the scope of the question a bit to include a few carefully chosen lossy options, so they don't pass the first
grep
filter in the above command.
-
So I ended up making my own answer too long.
TL;DR summary: For losslessly storing a sequence of images, use libx264
or libx264rgb
with -preset ultrafast -qp 0
. It's nearly as fast as ffvhuff, with much lower bitrate, and decodes faster. huffyuv
is much more widely supported outside of ffmpeg, but doesn't support as many pixel formats as ffvhuff
. So that's another reason to use h.264, assuming your other tools can handle the h.264 High 4:4:4 Predictive
profile that x264 uses in lossless mode. x264 can do intra-only if fast random access to arbitrary frames is needed.
Beware of a ffmpeg bug affecting libx264rgb when reading from a directory of images. (and who knows what other cases.) Test for losslessness in your setup before using. (easy with ffmpeg -i in -pix_fmt rgb24 -f framemd5
on source and lossless-compressed))
edit: utvideo
encodes and decodes fairly fast, and is a much simpler codec than h.264. It's basically a modern huffyuv
, with support for more useful colorspaces. If you ever have a problem with h.264, try utvideo next for temporary files.
edit2: PNG as a RGB codec appears to do well, at least on the Sintel trailer.
See also my similar answer to a similar question: https://superuser.com/a/860335/20798
There's a lot of info in the Warren Young's answer about various raw formats and codecs. I think the answer would be more useful if it was shorter, so I'm making a new answer. If you're working with software that doesn't support lossless x264 or ffvhuff, then some of that info is probably still useful.
The most useful definition of "lossless" in this context is that you can recover the input bit-for-bit. Zero worry about quality degradation from video encoding, regardless of what you do.
http://en.wikipedia.org/wiki/Chroma_subsampling
Ideally, avoid multiple colorspace conversions. The rounding errors can potentially build up. If you're going to operate on your video with filters that work in the RGB colorspace, then keeping it RGB makes sense, as long as the higher bitrates aren't an issue. You're probably going to ultimately produce a yuv 4:2:0
video, but keeping the extra chroma resolution is potentially useful, depending on what filters you're going to apply.
Either way, lossless x264 and ffvhuff both support RGB and yuv 4:4:4
, 4:2:2
, and 4:2:0
. I'd suggest x264, as it's fast to decode. If you're trying to play back RGB HD video in realtime, try opengl instead of xv, since xv on my system only accepts yuv input. mplayer was taking extra CPU time to do a color-space conversion.
Source for the following encoder tests: https://media.xiph.org/. https://media.xiph.org/sintel/sintel_trailer-1080-png.tar.gz They forgot to gzip the y4m files for the sintel trailer, so the png tarball is actually a lot smaller.
ffmpeg -i 1080/sintel_trailer_2k_%4d.png -i sintel_trailer-audio.flac \
-c:a copy -c:v libx264rgb -preset ultrafast -qp 0 \
frompng.sintel.264rgb.mkv
e.g.
peter@tesla:/mnt/GP1TB/p/encoder-sample/sintel$ time ffmpeg -i 1080/sintel_trailer_2k_%4d.png -i sintel_trailer-audio.flac -c:a copy -c:v libx264rgb -preset ultrafast -qp 0 frompng.sintel.264rgb.mkv
ffmpeg version N-67983-g2b358b4 Copyright (c) 2000-2015 the FFmpeg developers
built on Jan 10 2015 05:32:37 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --enable-gpl --enable-version3 --enable-nonfree --disable-doc --disable-ffserver --enable-libx264 --enable-libx265 --enable-libmp3lame --enable-libopus --enable-libwebp --enable-libvpx --disable-outdev=oss --disable-indev=oss --disable-encoder=vorbis --enable-libvorbis --enable-libfdk-aac --disable-encoder=aac --disable-decoder=jpeg2000
libavutil 54. 16.100 / 54. 16.100
libavcodec 56. 20.100 / 56. 20.100
libavformat 56. 18.100 / 56. 18.100
libavdevice 56. 3.100 / 56. 3.100
libavfilter 5. 7.100 / 5. 7.100
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 3.100 / 53. 3.100
Input #0, image2, from '1080/sintel_trailer_2k_%4d.png':
Duration: 00:00:50.12, start: 0.000000, bitrate: N/A
Stream #0:0: Video: png, rgb24, 1920x1080 [SAR 72:72 DAR 16:9], 25 fps, 25 tbr, 25 tbn, 25 tbc
Input #1, flac, from 'sintel_trailer-audio.flac':
Duration: 00:00:52.00, start: 0.000000, bitrate: 721 kb/s
Stream #1:0: Audio: flac, 48000 Hz, stereo, s16
File 'frompng.sintel.264rgb.mkv' already exists. Overwrite ? [y/N] y
No pixel format specified, rgb24 for H.264 encoding chosen.
Use -pix_fmt yuv420p for compatibility with outdated media players.
[libx264rgb @ 0x2770760] using SAR=1/1
[libx264rgb @ 0x2770760] using cpu capabilities: MMX2 SSE2Fast SSSE3 Cache64 SlowShuffle
[libx264rgb @ 0x2770760] profile High 4:4:4 Predictive, level 4.0, 4:4:4 8-bit
[libx264rgb @ 0x2770760] 264 - core 144 r2525+2 6a4fca8 - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=0 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=0 chroma_qp_offset=0 threads=3 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc=cqp mbtree=0 qp=0
Output #0, matroska, to 'frompng.sintel.264rgb.mkv':
Metadata:
encoder : Lavf56.18.100
Stream #0:0: Video: h264 (libx264rgb) (H264 / 0x34363248), rgb24, 1920x1080 [SAR 72:72 DAR 16:9], q=-1--1, 25 fps, 1k tbn, 25 tbc
Metadata:
encoder : Lavc56.20.100 libx264rgb
Stream #0:1: Audio: flac ([172][241][0][0] / 0xF1AC), 48000 Hz, stereo (16 bit)
Stream mapping:
Stream #0:0 -> #0:0 (png (native) -> h264 (libx264rgb))
Stream #1:0 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame= 1253 fps= 18 q=-1.0 Lsize= 834790kB time=00:00:51.96 bitrate=131592.5kbits/s
video:830198kB audio:4575kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.002025%
[libx264rgb @ 0x2770760] frame I:6 Avg QP: 0.00 size:612470
[libx264rgb @ 0x2770760] frame P:1247 Avg QP: 0.00 size:678787
[libx264rgb @ 0x2770760] mb I I16..4: 100.0% 0.0% 0.0%
[libx264rgb @ 0x2770760] mb P I16..4: 50.3% 0.0% 0.0% P16..4: 12.0% 0.0% 0.0% 0.0% 0.0% skip:37.6%
[libx264rgb @ 0x2770760] coded y,u,v intra: 71.1% 68.2% 70.0% inter: 22.8% 22.8% 23.2%
[libx264rgb @ 0x2770760] i16 v,h,dc,p: 50% 48% 1% 1%
[libx264rgb @ 0x2770760] kb/s:135693.94
Note that I forgot to specify -r 24
fps, so it won't keep av sync with the audio. (and the bitrate (but not file size) numbers will be off, too. ffmpeg defaults to 25fps). CPU in this machine is a 1st-gen (conroe) core2duo 2.4GHz (E6600).
results:
4.5M sintel_trailer-audio.flac # this is muxed in to every mkv
948M 1080 # the directory of PNGs
940M /var/tmp/dl/sintel_trailer-1080-png.tar.gz
7434M sintel.y4m # yuv444, uncompressed. mplayer gets the colors wrong?
2342M qtrle.mkv # encode went at 16fps, so qtrle is slower and worse filesize
2105M sintel.huff.mkv # ffvhuff with default options, rgb pix fmt
1228M sintel.utvideo.mkv # muxed without audio, I should update the others this way
946M png-copy.mkv # -codec copy makes a MPNG stream. Use -codec png for non-png sources, but it won't make PNGs as small. Decodes very fast
824M lossy.prores_ks.mov # yuv444p10le extremely slow to encode (2.3fps), and worse bitrate.
816M frompng.sintel.264rgb.mkv
735M sintel.x264rgb.medium.nocabac.mkv # encode went at 3.3 fps instead of 18. Better gain than for live-action, though
626M sintel_trailer.rgb.lossless.veryslow.mkv # 1.1fps. With CABAC, 16 ref frames, etc. etc.
512M lossy.prores.mov # yuv422p10le, 12fps
341M sintel.yuv420.x264.lossless.mkv
21M lossy.rgb.crf26.preset=medium.mkv
13M lossy.yuv420.crf26.preset=medium.mkv # remember this is WITH 4.5MB audio
Note that mediainfo
doesn't know about RGB h.264, it still says that the files are YUV.
Check that it really was lossless:
ffmpeg -i 1080/sintel_trailer_2k_%4d.png -f framemd5 png.framemd5
ffmpeg -i fromhuff.sintel.264rgb.mkv -an -sn -pix_fmt rgb24 -f framemd5 x264rgb.framemd5
diff -s *.framemd5
Files png.framemd5 and x264rgb.framemd5 are identical
So you can recover the original PNG input that way, i.e. you could make PNGs with identical image data in them.
Note the -pix_fmt rgb24
for the x264 test. ffmpeg's h.264 decoder outputs gbrp (planar, not packed) output, so the bits are the same, but in a different order. The framemd5 "container" doesn't impose any sort of format restrictions, but you'll only get the same md5 if the bits are arranged the same way. I just looked at what ffmpeg said it was using for a pix fmt when I fed it PNGs, then used that as the arg to -pix_fmt
for decode. Incidentally, this is the reason vlc won't play RGB h.264 files (until next release, or current nightly builds): It doesn't support the gbrp pixel format.
For yuv use libx264
, not libx264rgb
. You don't need to install an RGB version of x264, the actual library supports both. It's just ffmpeg that implemented it as two differently named encoders. I think if they hadn't done that, the default behaviour would be to leave rgb input as rgb, and run really slowly while producing much higher bitrate output for the same quality. (you still sometimes have to use -pix_fmt yuv420p
if you want 420
instead of 444
h.264 output.
Unless you are making files for long-term storage, always use -preset ultrafast
for lossless x264. More reference frames and motion search barely makes any difference for lossless, for non-animated material with any noise. CABAC takes a huge amount of CPU at lossless bitrates, even to decode. Only use for archival purposes, not scratch files. (ultrafast disables CABAC). CABAC gives 10 to 15% bitrate savings.
If you need every frame to be a keyframe, set -keyint 1
. Then video editing software that only wants to cut on keyframes or w/e will not limit you.
To answer the original question: This is what you should do for throwing around temporary files while trying things in stages (e.g. a slow deinterlace, saving lossless output before trying other things):
ffmpeg -i dv-video-source.ts -vf yadif=2:1,mcdeint=3:1:10 -c:a copy -c:v libx264 -preset ultrafast -qp 0 deinterlaced.mkv
If you really need your output in image files that you can modify with still-image tools, then sure, decode to png. You're not going to lose anything more than maybe the least significant of the 8 bits of for each of the Y, Cb, and Cr values for each pixel.
x264 comes out REALLY well in this because there are a lot of black frames with a bit of text, a fade-in and fade-out, and perfect similarity between big areas of many frames, which it manages to take advantage of even with -preset ultrafast
. On live-action, I still see x264 at half the filesize of ffvhuff (yuv420).
For anyone curious: The high-cpu-time lossless rgb encode had (x264 core 144 r2525):
[libx264rgb @ 0x35b97a0] frame I:27 Avg QP: 0.00 size:604367
[libx264rgb @ 0x35b97a0] frame P:1226 Avg QP: 0.00 size:517512
[libx264rgb @ 0x35b97a0] mb I I16..4..PCM: 46.3% 38.1% 15.7% 0.0%
[libx264rgb @ 0x35b97a0] mb P I16..4..PCM: 24.3% 5.4% 4.5% 0.0% P16..4: 10.5% 3.3% 5.7% 0.0% 0.0% skip:46.3%
[libx264rgb @ 0x35b97a0] 8x8 transform intra:17.3% inter:46.1%
[libx264rgb @ 0x35b97a0] coded y,u,v intra: 81.6% 77.5% 80.0% inter: 28.0% 27.7% 28.1%
[libx264rgb @ 0x35b97a0] i16 v,h,dc,p: 35% 64% 1% 0%
[libx264rgb @ 0x35b97a0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 31% 49% 13% 2% 1% 1% 1% 1% 1%
[libx264rgb @ 0x35b97a0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 31% 37% 5% 5% 6% 5% 5% 4% 3%
[libx264rgb @ 0x35b97a0] Weighted P-Frames: Y:41.1% UV:40.7%
[libx264rgb @ 0x35b97a0] ref P L0: 74.5% 4.2% 9.1% 4.1% 2.1% 1.7% 1.2% 0.8% 0.6% 0.5% 0.3% 0.2% 0.2% 0.2% 0.2% 0.1%
[libx264rgb @ 0x35b97a0] kb/s:99721.66
Note the really high fraction of weighted p frames, and also the really high fraction of skip macroblocks. Every scene transition is a fade, not a cut, and x264 takes advantage if you give it the CPU time to figure out how.
further notes (lossy codecs for editting):
For scrubbing forwards/backwards through clips, intra-only codecs are usually favoured (utvideo, ffvhuff, mjpeg, jpeg2000, pro-res, AVC-Intra). I'd imagine regular AVC with short GOPs (1/2 to 1 sec) would scrub pretty well, too, as long as the software knew what it was doing (decode nearest I frame when scrubbing fast, decode within the GOP to get to an inter frame if you're zoomed in enough on a timeline for that to be needed).
I've posted some negative things on this and https://video.stackexchange.com/ about pro-res, like "what's the point if it's slower and worse compression than a lossless codec", but it does have some interesting features. Apple says that it can decode at half-resolution using as little as 1/3 the CPU time of decoding full rez.
ffmpeg's prores implementation is probably not as optimized for speed as Apple's either, which is why my testing with ffmpeg has made it look slow. It's probably not worth using if you have a Free software workflow with tools based on ffmpeg, but it might be worth trying if you're using commercial software.
I don't do a lot of video editting, mostly just encoding, so I don't have a good sense of what tests would be appropriate for codecs like prores. I'd guess that maybe mjpeg would be a good fast alternative, if short-GOP x264 doesn't work well. There are asm-accelerated implementations of jpeg in Linux distros, and it's a pretty simple codec. You can turn the quality up or down as needed to trade off quality vs. filesize + encode/decode speed. It's ancient, but if you want an intra-only codec that's really fast, it might beat x264.
For x264, I'd try something like x264 --crf 10 --keyint=1 --preset superfast --tune fastdecode
(Intra-only, without any of the other stuff that --avcintra-class
sets.) Note superfast
(without CABAC), or faster
, not ultrafast
is probably best for lossy operation. I think ultrafast loses a lot of quality without being that much faster. The lower quality (higher crf) you use, the more it's worth spending a bit more CPU time finding a better encode. A lot of this probably isn't relevant with GOP size = 1, though.
With GOP size > 1, if you're throwing so many bits at the encode that better inter-prediction won't save many bits when encoding the residuals (because noise / grain / subtle changes between frames are getting preserved very accurately), then just superfast is probably fine. Otherwise, with --keyint=30
or something, probably --preset veryfast --crf 12
would be interesting.
In theory, quality at a given CRF setting should be constant across presets. If you're looking for smaller files (faster decodes), trading off some quality and some encode time makes sense.