Producing lossless video from set of .png images using ffmpeg

I have a set of .png images that I would like to animate into a movie using ffmpeg on macOS, but when I look at the video produced the quality is always compressed and the resulting video has artifacts when the original image does not. Here is an image from the video as well as the same section of the original image. I have tried encoding using the h.264 codec with crf = 0, but am getting a strange error when I run ffmpeg:

Codec AVOption crf (Select the quality for constant quality mode) specified for output file #0 (test.mp4) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.

I used the following ffmpeg command to generate this:

ffmpeg -f image2 -r 10 -i image%05d.png -vcodec h264 -crf 0 -y test.mp4

One possibility is that it is disabled (see in the full console output below), but that doesn't make sense to me because it does show up when I list the ffmpeg codecs with ffmpeg -codecs as

DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: h264_videotoolbox )

Here is the full console input/output:

ffmpeg -f image2 -r 10 -i image%05d.png -vcodec h264 -crf 0 -y test.mp4
ffmpeg version 4.0 Copyright (c) 2000-2018 the FFmpeg developers
  built with clang version 4.0.1 (tags/RELEASE_401/final)
  configuration: --prefix=/Users/user/anaconda3 --cc=x86_64-apple-darwin13.4.0-clang --disable-doc --enable-shared --enable-static --enable-zlib --enable-pic --enable-gpl --enable-version3 --disable-nonfree --enable-hardcoded-tables --enable-avresample --enable-libfreetype --disable-openssl --disable-gnutls --enable-libvpx --enable-pthreads --enable-libopus --enable-postproc --disable-libx264
  libavutil      56. 14.100 / 56. 14.100
  libavcodec     58. 18.100 / 58. 18.100
  libavformat    58. 12.100 / 58. 12.100
  libavdevice    58.  3.100 / 58.  3.100
  libavfilter     7. 16.100 /  7. 16.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  1.100 /  5.  1.100
  libswresample   3.  1.100 /  3.  1.100
  libpostproc    55.  1.100 / 55.  1.100
Input #0, image2, from 'image%05d.png':
  Duration: 00:00:25.00, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: png, rgba(pc), 1382x1036 [SAR 2834:2834 DAR 691:518], 10 fps, 10 tbr, 10 tbn, 10 tbc
Codec AVOption crf (Select the quality for constant quality mode) specified for output file #0 (test.mp4) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.
Stream mapping:
  Stream #0:0 -> #0:0 (png (native) -> h264 (h264_videotoolbox))
Press [q] to stop, [?] for help
GVA info: Successfully connected to the Intel plugin, offline Gen95 
[h264_videotoolbox @ 0x7fc150018600] Color range not set for yuv420p. Using MPEG range.
Output #0, mp4, to 'test.mp4':
  Metadata:
    encoder         : Lavf58.12.100
    Stream #0:0: Video: h264 (h264_videotoolbox) (avc1 / 0x31637661), yuv420p, 1382x1036 [SAR 1:1 DAR 691:518], q=2-31, 200 kb/s, 10 fps, 10240 tbn, 10 tbc
    Metadata:
      encoder         : Lavc58.18.100 h264_videotoolbox
frame=   82 fps=0.0 q=-0.0 size=       0kB time=00:00:07.70 bitrate=   0.0kbits/frame=  196 fps=195 q=-0.0 size=     256kB time=00:00:19.10 bitrate= 109.8kbits/frame=  250 fps=198 q=-0.0 Lsize=     616kB time=00:00:24.90 bitrate= 202.5kbits/s speed=19.7x    
video:614kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.305027%

Solution: Apparently it was in fact the --disable-libx264 tag that was my problem. Apparently its necessary to install ffmpeg from conda-forge rather than the standard anaconda in order to be able to encode x264 video.


Solution 1:

You're using a generic value for -vcodec which in your case selects the encoder named h264_videotoolbox. This encoder does not use -crf. Instead, be specific when selecting an encoder and use libx264 (or libx265) instead:

ffmpeg -framerate 10 -i image%05d.png -c:v libx264 -crf 0 output.mp4

If you want to avoid the RGB to YUV colorspace conversion use libx264rgb:

ffmpeg -framerate 10 -i image%05d.png -c:v libx264rgb -crf 0 output.mp4

If you just want to make a lossless video of PNG you can keep the images as is:

ffmpeg -framerate 10 -i image%05d.png -c:v copy output.mkv