How to convert videos to WebM with FFmpeg/AVConv

After lots of trial and error each time I convert a video to WebM, I finally got around to posting this so I don’t forget next time. In a nutshell, here’s the conversion command that works for me:

avconv -i myvideo.mp4 -acodec libvorbis -aq 5 -ac 2 -qmax 25 -threads 2 myvideo.webm

What is this doing? Let’s go through it bit by bit. Assuming we have a video called myvideo.mp4, the simplest way to convert to WebM is with this little line:

avconv -i myvideo.mp4 myvideo.webm

Easy, but the quality will likely be rubbish hence the use of a few flags. The flags can be divided into three sorts: audio, video and the transcoding itself.

Audio flags

FFmpeg/AVConv outputConcentrating on the audio first, we should specify the audio codec which for WebM is Ogg Vorbis: -acodec libvorbis

In later versions the audio codec is Ogg Vorbis by default but personally I specify it just in case.

The quality can be adjusted with the -aq flag from -1 to 10 with a higher number meaning better quality. I’ve found 4 or 5 to be more than adequate.

The number of channels, e.g. mono (1) and stereo (2), is controlled with the -ac flag.

Video flags

Moving on to the video quality and thankfully it’s nice and simple. Like the audio, we can specify a quality level. With the libvpx library used for WebM, this is actually a quantization level, set with the -qmin and -qmax flags ranging from 0 to 51. In my tests, setting qmin makes no difference so I ignore it. Setting qmax effectively controls the maximum compression that will be applied to each frame. In other words, a higher qmax means higher compression, which results in lower quality and smaller file size. Obviously you should adjust this to whatever’s best for your circumstances, but I’ve found 25 to be a good starting point.

Note that with both the audio and video, setting flags for bitrate (-ab for audio, -b for video) makes little or no difference. Instead, setting quality flags indicates the use of a variable bitrate.

Transcoding flags

Finally, I tend to also use the -threads flag. This simply sets how many CPU threads to use when transcoding. If your PC has multiple cores then a higher number means faster processing but with less spare capacity for running other programs. Incidentally it’s also possible to do 2-pass encoding with WebM using the -pass flag.

FFmpeg naming confusion

Note that due to what seem to be political reasons, using the ffmpeg command in Ubuntu results in a sad message.

Was:

*** THIS PROGRAM IS DEPRECATED ***
This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.

Now:

ffmpeg: command not found

It turns out that FFmpeg is very much alive, as is Libav (avconv), both with similar goals but with slightly different ways of doing it. I don’t follow the details and arguments but for practical purposes, using either the ffmpeg or avconv command is fine for converting videos to WebM with the above flags (at the time of writing). Of course, this may change eventually but for the sake of regular users, I hope not.

Unfortunately whatever FFmpeg/Libav disagreement there was has resulted in ffmpeg being removed from Ubuntu and possibly other Linux distros. For the transcoding commands in this post at least, the parameters are the same so if you have problems using avconv try with ffmpeg and vice versa.

14 thoughts on “How to convert videos to WebM with FFmpeg/AVConv

  1. Chiranjivi

    Hi, can you please tell me how to use the same in command prompt using windows.

    here is the code which i am using “ffmpeg -i input.mp4 -vcodec libvpx -acodec libvorbis -f webm movie.webm”

    Reply
      1. Daniel Post author

        Hi Chiranjivi,

        I’m not familiar with Windows but it sounds like the WebM (VP8) codec is not installed. I found instructions on the official WebM site for installing DirectShow filters which should be what you need: http://www.webmproject.org/tools/

        I suggest giving this a try and I’d be interested to hear if it does or doesn’t work.

        Reply
  2. Alwyn

    Thank you! You just fixed the problem that has been plaguing me for the last few months– namely, that every video converted I tried produced a .webm file four times larger than the source .mp4, with worse quality. Video looks good, and the file size is roughly the same. Thank you!!

    Reply
    1. Daniel Post author

      You’re welcome!

      It took me a lot of trial and error so it’s very satisfying to know I’ve helped someone. Thanks for letting me know.

      Reply
  3. Nick

    Hi,
    This was very helpful. I actually used it in my PHP script and it worked like a champ. On 2 threads too.

    If someone wants to convert MP4 to another MP4 with a higher quality video try this:


    input.mp4 -c:v libx264 -crf 17 output.mp4

    I am wandering if you can help me with the command to convert my mp4 to ogv? So far I have your code snippet above (thanks again) and my MP4 one above.

    I have tried:

    -c:v libtheora -q:v 10 -c:a libvorbis -q:a 10

    It looks good, the audio plays but the video stops after 1 second.

    Any help greatly appreciated!

    Your fellow developer,
    Nick

    Reply
    1. rahul

      is there any way to put the loader if conversion process running this is my code

      var video_path=video[‘path’];
      console.log(‘path sync function: ‘ + video_path);

      var fileNameIndex = video_path.lastIndexOf(“/”) + 1;
      //var fileNameIndex = path_f.lastIndexOf(“/”) + 1;
      var filename = video_path.substr(fileNameIndex);
      //var path = filename;
      console.log(‘filename: ‘ + filename);
      var webm_file =”public/upload/”+filename;
      console.log(‘webm_file.myyy.webm: ‘ + webm_file);
      var mp_file =”public/upload/”+Math.random()*1000000000000000000+’.mp4′;
      console.log(‘mp_file.myyy.mp4: ‘ + mp_file);

      var convert = “c:/ffmpeg/bin/ffmpeg -i ” + webm_file + ” ” + mp_file ;
      console.log(‘convert: ‘ + convert);

      //var path = convert;
      var test=exec(convert);
      console.log(‘test: ‘ + test);

      var fileNameIndex_db = mp_file.lastIndexOf(“/”) + 1;
      var filename_db = mp_file.substr(fileNameIndex_db);
      var path= “upload/”+filename_db;
      console.log(‘path save in db: ‘+path);

      Reply
  4. Faron the Falcon

    Howdy there — nice article…but, with updated information. For Ubuntu – FFMPEG has been reinstated in the repository. `sudo apt-get install ubuntu-restricted-extras ubuntu-restricted-addons`.

    Cheers

    Reply

Leave a Reply to rahul Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>