I'm doing an animation for a projection mapping that simulates the sun casting shadows on a structure as it moves through the sky. Basically it's just big flat areas of colour that change over about five minutes as the "sun" rises and sets (in another projection). It's played off a Brightsign playback gizmo, and I'm using h.264 main profile as the codec in an mp4.

The problem I'm having is that the encoding isn't dealing very well with the content. Even though the colour is completely flat, when the pixels all change value over time I'm getting bands of noise and blocks appearing. They're subtle, but they're annoying.

Is there any tuning I can do using libx264 to optimise it for large flat areas of colour where all the pixels simultaneously change over time? There is absolutely no movement in the frame, just the colour of the whole area changing, quite slowly.

My current ffmpeg command is pretty generic:

ffmpg -i input.mov -c:v libx264 -preset slow -profile main -crf 20 -pix_fmt yuv420p -an output.mp4
  • Please include the complete ffmpeg console output. Can you provide a short input sample? Does reducing -crf to ~18 help? Does -tune animation make a difference? If nothing helps you can look into using the gradfun video filter upon playback.
    – llogan
    Commented Mar 27, 2014 at 17:44

3 Answers 3


The bands you're referring to could well just be a limitation of the 8-bit colour space.

In theory the way to solve this is to use 10- or 12-bit colour space through every stage from rendering, to editing and mastering, through to output and even in the screen or projector. However your final output is probably going to be displayed in an 8 bits per channel space whether you like it or not.

So the practical way to do this is to render at 10- or 12-bit colour and dither down to 8-bit from the master. The dithering will prevent the visual appearance of banding when displayed at 8 bits per channel.

Note that this is not a limitation of h.264 or any encoder but of the colour space used and the noise-free nature of the rendered animation; if real life was this noise-free it would also show this banding in 8-bit colour spaces. There is unlikely to be any setting you could choose in your encoder in order to solve this. To confirm, render to an uncompressed format and you will probably still see the banding.

Note: dithering from a 10- or 12-bit render is not the same as just adding some noise to an existing 8-bit dither - while this may disguise the banding a little bit simply by making it less distinct it doesn't solve it. But you could do it in a pinch.

  • thanks, but it's probably not the limitations of the 8-bit output. Banding occurs with gradients. These are flat areas of colour, with every pixel the same value. The compression is introducing the banding as the the pixels change in time.
    – stib
    Commented Apr 1, 2014 at 2:40
  • 1
    In that case have you played with lower CRF values? 20 may not be transparent in mostly flat areas of color with animation. With rendered animation you should be able to get away with much lower CRF values (such as 16). You can test with something very high quality like 10 or even lossless just as a point of troubleshooting to see if the quantization is a factor at all. Commented Apr 1, 2014 at 23:51

Depending how the content was made, the banding might be introduced when you're converting your content from RGB colorspace to YUV. You can try to make an h264 while keeping RGB colorspace, although I've read it's not easy. Are you able to use another codec?


The first thing I would try is to add -force_key_frames to your original command, drop the preset and lower the -crf value. The following example sets a key frame every second.

ffmpg -i input.mov -c:v libx264 -profile main \
    -force_key_frames expr:gte(t,n_forced*1) \
    -crf 15 -pix_fmt yuv420p -an output.mp4

As a second resort I would use a series of png images (instead of mov) as the input and use a very low crf. This way you can really make sure that there is no banding in your input and the highest quality in the end material. If you can't directly render to png, then convert the original material.

Here is an example:

# turn the original into pngs
ffmpeg -i input.mov -f image2 -threads 0 /tmp/%05d.png

# turn the pngs back into mp4 (assuming 25 fps)
ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -r 25/1 -f image2 \
  -i /tmp/%05d.png -c:a libfdk_aac -c:v libx264 \ 
  -profile main -vf "fps=fps=25" -force_key_frames expr:gte(t,n_forced*1) \
  -crf 10 -threads 0 -pix_fmt yuv420p output.mp4

ps. You should get in the habit of including a silent audio track for media device playback because of syncing issues.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.