What is the best way to convert a mp4 file to webm without quality loss (using vp8 or vp9) with ffmpeg?

If I do ffmpeg -i in.mp4 out.webm the quality is very bad. I can specify a target bitrate via -b:v and constant quality mode via crf, i.e.

ffmpeg -i in.mp4 -crf 10 -b:v 1M out.webm

This gives better quality. However for this I have to lookup the bitrate of the input video (here 1M).

I also noticed that if you specify a much larger value for the target bitrate than the bitrate of the input (here for example -b:v 100M), ffmpeg just seems to use approximately the bitrate from the input video with vp9 or slightly higher bitrate with vp8. However this solution doesn't seem to be the intended way to do this.

How would you choose the crf value and why?

Is there a parameter which automatically chooses the bitrate of the input file and a suitable crf value to get the same quality as the input file?

  • Set bitrate to 0. And experiment with crf. But your method of a high bitrate works too, since the value acts as a ceiling not a target
    – Gyan
    Oct 15 '16 at 18:22
  • 1
    @Mulvya: Does bitrate 0 mean that there is no limit? I didn't find this in the man page.
    – student
    Oct 15 '16 at 19:21
  • With bitrate not set to zero, CRF is constrained by that value. With zero, it's not. It's a quirk of the VPn encoders.
    – Gyan
    Oct 17 '16 at 3:14
  • Ok, but if I omit the bitrate parameter completely the quality gets very bad even thoug I didn't give an upper limit for the bitrate.
    – student
    Oct 17 '16 at 11:57
  • 1
    Link for 200k (see first option). For WebM b:v 0, see this page.
    – Gyan
    Oct 17 '16 at 12:33


Use two-pass Constant Quality mode:¹

ffmpeg  -i input.mp4  -b:v 0  -crf 30  -pass 1  -an -f webm -y /dev/null
ffmpeg  -i input.mp4  -b:v 0  -crf 30  -pass 2  output.webm


Setting the video bitrate to zero while also specifying the CRF (Constant Rate Factor) enables Constant Quality mode which targets a certain perceptual quality level. For VP9, the CRF can range from 0 (best quality) to 63 (smallest file size).

It is important to set the video bitrate to zero. If you do not specify a video bitrate, it defaults to something low which gets you Constrained Quality mode, where each frame has a maximum bitrate. While that can be useful for streaming, it reduces quality significantly as frames with a lot of motion will not have the bandwidth needed to look good.

Another part of the reason you’re losing quality is that webm (VP9) prefers to encode in two passes for best results. The first pass compiles statistics about the video which is then used in the second pass to make a smaller and higher quality video.

Please see the ffmpeg VP9 documentation if you’d like to learn more.

A word about transcoding

By the way, in general, transcoding formats (taking a compressed video and recompressing it with a different codec) is a bad idea as you’ll not only add the normal errors from lossy video encoding, but you’ll waste bits in the new format trying to preserve the artifacts from the old.

If you mean “without quality loss” literally

The -lossless 1 option of ffmpeg’s VP9 encoder enables lossless quality mode, but with a potentially enormous increase in filesize.

All you need is this:

ffmpeg  -i input.mp4  -lossless 1  output.webm

When I tried -lossless 1 on a low-quality mp4, the resulting webm was 100× larger, which was not accceptable to me. However, if your mp4 files are already very high quality, I expect the size difference will not be so great.

Footnote 1: If you're using Microsoft Windows instead of UNIX, change /dev/null to NUL.

  • 1
    Great answer thanks
    – yachaka
    Jan 15 '20 at 11:49
  • /dev/null? What does this mean? What would the equivalent be for windows users? Are you overwriting input.mp4 on the first pass? This answer needs more explanation on what exactly each component is doing. It doesn't offer intermediate users much explanation of how it works.
    – Hatefiend
    Feb 16 '20 at 9:01
  • 1
    Hi Hatefriend: My answer already includes a long explanation section plus a link for more information, so I'd rather not make it longer. Did you see the footnote regarding Microsoft Windows which answers your specific question? Also, as mentioned above, the first pass compiles statistics about the input file. There is no need to fear that it might overwrite the input.
    – hackerb9
    Feb 20 '20 at 4:09
  • I tried convert .MTS file to .webm usig these two commands (Ubuntu 20.10, ffmpeg version 4.2.2). But I have got errors: "Invalid channel layout 5.1(side) for specified mapping family -1. Error initializing output stream 0:1 -- Error while opening encoder for output stream #0:1 - maybe incorrect parameters such as bit_rate, rate, width or height" May 2 '20 at 14:54
  • thanks for the answer. if transcoding is generally a bad idea, what do you recommend instead if you need to convert mp4 videos to webm and webm videos to mp4?
    – Crashalot
    Jan 9 at 9:43

On Linux I use optimizeVideo, which is a wrapper around ffmpeg that automatically detects those settings according to Google's recommendations.

The result is a video which quality difference you cannot tell, but usually orders of magnitude smaller.


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.