So I ended up making my own answer too long.
TL;DR summary: For losslessly storing a sequence of images, use
-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))
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:
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.
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: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 \
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':
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
encoder : Lavc56.20.100 libx264rgb
Stream #0:1: Audio: flac ( / 0xF1AC), 48000 Hz, stereo (16 bit)
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).
4.5M sintel_trailer-audio.flac # this is muxed in to every mkv
948M 1080 # the directory of PNGs
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.
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
13M lossy.yuv420.crf26.preset=medium.mkv # remember this is WITH 4.5MB audio
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.
-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
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 http://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
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.