I am encoding png image sequences to both webm and mp4 formats using ffmpeg. My goal is to achieve perceptually lossless videos, with the smallest file size I can reasonably achieve.

The webm videos I produced worked fine and were playable in many browsers, until I switched to a later version of ffmpeg, which I compiled from source. (The reported ffmpeg version is N-91380-g46fb150, whatever that means).

The output webm videos still played fine in VLC, but browsers like Chromium and Opera would display them with the colors totally messed up. It seems like the blue in the video is mostly replaced with green - anyway it looks really weird.

I checked the color mode with ffprobe on the videos produced with old and new versions of ffmpeg:

The old ffmpeg webm videos that worked everywhere:
vp9 (Profile 1), yuv444p(tv)
The new ffmpeg webm videos, which work in VLC, but have messed up colors in browsers:
vp9 (Profile 1), gbrp(pc, gbr/unknown/unknown, progressive)

The ffmpeg command I was using didn't specify any pix_format - and I'm pretty sure it was something like this accross old and new ffmpeg versions:
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -i my_audio.flac -c:v libvpx-vp9 -b:v 0 -tile-columns 2 -crf 18 -c:a libopus -b:a 128k -r 30 -g 300 -y my_video.webm

I read somewhere about pix_format and tried this (note the yuva420p option):
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -i my_audio.flac -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 0 -tile-columns 2 -crf 18 -c:a libopus -b:a 128k -r 30 -g 300 -y my_video.webm

I chose yuva instead of yuv in the hopes it would enable the alpha channel, because my input png images have transparency. It seemed to work... the videos now play fine in browsers, like with the old version of ffmpeg. Compared to the old ffmpeg result with default pix_format, ffprobe shows a slight difference. It reports:
vp9 (Profile 0), yuv420p(tv, progressive) and alpha_mode: 1

Interestingly, the output webm file size using yuva420p is smaller than if I omit the pix_format option. With yuva420p it's about 2/3 the size of the output file that uses the default gbrp mode and messes up colors in browser playback.

So it seems like pix_fmt yuva420p is the way to go. But since I really have no idea about color spaces / pixel formats, my question is: What color mode / pix_format option should I choose, given I want high quality webms, small'ish file size, and compatibility with many browsers? Are there any drawbacks with using yuva420p instead of the default gbrp, or another pix_format option?

And for bonus points ;) if yuva420p is OK, why would ffmpeg change the default pix_format value away from yuv to gbrp?


YUV color encoding with 4:2:0 chroma subsampling is the only widely safe pixel format for web playback, although for certain codecs, other pixel formats may be supported.

FFmpeg auto-selects the pixel format for the output as not all encoders support all pixel formats. It will select the pixel format which best preserves the source bit depth, chroma sampling scheme and the color encoding scheme, from among the formats supported by the encoder. PNGs have RGB pixel format and until two years ago, ffmpeg did not support encoding RGB formats for the VPx encoders, so it would select a YUV format with full chroma (4:4:4). Since RGB became supported in FFmpeg for VPx, it will select a RGB variant like gbrp.

Auto-selection is overriden by manually specifying -pix_fmt.

YUV streams can be more efficiently compressed than RGB.

  • Thanks Gyan... your comments make enough sense so I'm accepting this answer, even though I find ffmpeg's default choice of chroma subsampling for PNG to VP9 encoding rather unhelpful and confusing. – Framerate Jul 31 '18 at 2:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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