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