<h1>Answer</h1>
<p>Use two-pass Constant Quality mode:</p>
<pre><code>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
</code></pre>
<h2>Notes</h2>
<ol>
<li><p>If you're using Microsoft Windows™ instead of UNIX, change <code>/dev/null</code> to <code>NUL</code>.</p>
</li>
<li><p>We discard the video using <code>/dev/null</code> because the first pass's only purpose is to generate a log file of statistics.</p>
</li>
</ol>
<h2>mp42webm shell script</h2>
<p>To save typing in the future, this can be put in a UNIX shell script:</p>
<pre class="lang-sh prettyprint-override"><code>#!/bin/sh -xe
ffmpeg -i &quot;$1&quot; -b:v 0 -crf 30 -pass 1 -an -f webm -y /dev/null
ffmpeg -i &quot;$1&quot; -b:v 0 -crf 30 -pass 2 &quot;${1%.mp4}.webm&quot;
</code></pre>
<p>Usage: <strong>mp42webm</strong> <em>filename</em>.mp4. <br/>
Creates <em>filename</em>.webm.</p>
<h2>Explanation:</h2>
<p>Setting the video bitrate to <em>zero</em> 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).</p>
<p>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 <em>Constrained</em> 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.</p>
<p>Another part of the reason you’re losing quality is that <code>webm</code> (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.</p>
<p>Please see the <a href="https://trac.ffmpeg.org/wiki/Encode/VP9" rel="nofollow noreferrer">ffmpeg VP9 documentation</a> if you’d like to learn more.</p>
<h2>A word about transcoding</h2>
<p>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.</p>
<h2>If you mean “without quality loss” literally</h2>
<p>The <code>-lossless 1</code> option of ffmpeg’s VP9 encoder enables lossless quality mode, but with a potentially enormous increase in filesize.</p>
<p>All you need is this:</p>
<pre><code>ffmpeg  -i input.mp4  -lossless 1  output.webm
</code></pre>
<p>When I tried <code>-lossless 1</code> on a low-quality <code>mp4</code>, the resulting <code>webm</code> was 100× larger, which was not accceptable to me. However, if your <code>mp4</code> files are already very high quality, I expect the size difference will not be so great.</p>

CC BY-SA 4.0
2020-02-16T09:01:59.980Z
`/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
CC BY-SA 4.0
2020-02-20T04:09:43.083Z
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
CC BY-SA 4.0
2020-05-02T14:54:25.227Z
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"
Andrew Krizhanovsky
CC BY-SA 4.0
2021-01-09T09:43:28.930Z
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
CC BY-SA 4.0
2021-02-08T22:59:53.030Z
Hmm. That didn't work. Second command failed: "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"
Ken Ingram
CC BY-SA 4.0
2021-07-16T13:28:43.540Z
`File '/dev/null' already exists. Overwrite ? [y/N]` so I will switch it to /tmp/deleteme.webm
reducing activity
CC BY-SA 4.0
2021-08-02T00:51:33.637Z
@reducingactivity Thanks for letting me know that ffmpeg changed the default behaviour. It is safe to answer 'y" when writing to /dev/null as it is a fake file that ignores anything written to it. I've updated my answer to include the `-y` flag so that people won't be asked "Overwrite?".
hackerb9
CC BY-SA 4.0
2022-05-16T15:54:01.627Z
I think it is silly that 2 passes cannot be accomplished with one command. When I see two separate commands like this it makes me worry that the 2nd command will not even take into consideration what is accomplished by the first command.
Lonnie Best
CC BY-SA 4.0
2023-08-10T13:53:19.477Z
Would this work going the other way? ```ffmpeg  -i input.webm  -lossless 1  output.mp4```
majorgear
CC BY-SA 4.0
2023-08-10T20:49:05.290Z
Good question. The answer is no, lossless mode is a feature of webm.
hackerb9
CC BY-SA 4.0
2019-08-15T06:16:05.000Z
2024-02-27T07:18:39.503Z
2024-02-27T07:18:39.503Z
hackerb9
<p>On Linux I use <a href="https://gitlab.com/es20490446e/optimizeVideo" rel="nofollow noreferrer">optimizeVideo</a>, which is a wrapper around ffmpeg that automatically detects those settings according to <a href="https://developers.google.com/media/vp9/settings/vod/" rel="nofollow noreferrer">Google's recommendations</a>.</p>
<p>The result is a video which quality difference you cannot tell, but usually orders of magnitude smaller.</p>
<p><a href="https://i.sstatic.net/BQMCT.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/BQMCT.png" alt="Logo" /></a></p>

CC BY-SA 4.0
2020-07-04T00:06:56.963Z
2020-07-04T00:06:56.963Z
Alberto Salvia Novella
<p>mp4 and webm are container formats. think of them as boxes that contain within them various video, audio, subtitle, chapter info, etc files.</p>
<p>if all the streams within the source mp4 container file are compatible with webm container format then it can be losslessly converted to webm, this is called remuxing (aka stream copy). This process simply copies the individual streams from one container to another without changing them in any way.</p>
<p>which is an extremely quick process and also lossless, has a trivial effect on file size (from mp4 to webm you save a bit of space). There is no generational quality loss due to not modifying the video and audio streams.</p>
<p><a href="https://ffmpeg.org/ffmpeg.html#Stream-copy" rel="nofollow noreferrer">https://ffmpeg.org/ffmpeg.html#Stream-copy</a></p>
<pre><code>ffmpeg -i input.mp4 -c copy output.webm
</code></pre>
<p>I have tested the above command myself and it works great. if the mp4 container is using streams that are NOT compatible with webm. (for example h264 video. or srt subtitles). Then you cannot remux / stream copy it.</p>
<p>If one of the streams you are trying to pass to webm is unsupported it will instead error out and inform you that:</p>
<blockquote>
<p>Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.</p>
</blockquote>
<p>you would have to resort to re-encoding the unsupported stream. if you are re-encoding the video it is a lengthy process that will cause a variable hit to the image quality</p>
<p>near negligible is possible with the right settings and quality input. although doing so might take a long time and a lot of space. depending on the exact details of input and output codec and configuration. furthermore each time you convert via re-encoding you suffer generational loss. so even negligible losses add up to serious losses if you do it over and over.</p>
<p>technically, you can re-encode it into a lossless format or lossless setting. But doing so will result in obscenely large files. Making them impractical for many uses. realistically you won't be wanting to do that.</p>

CC BY-SA 4.0
2024-09-13T11:17:25.720Z
Your post doesn't seem to answer the question
Dr Mayhem
CC BY-SA 4.0
2024-09-22T17:19:38.043Z
@Dr Mayhem please reread. it clearly answers the question. He wanted to losslessly convert mp4 to webm using ffmpeg. I gave him the command to do so, being `ffmpeg -i input.mp4 -c copy output.webm` with the caveat that it can only be losslessly converted if the source mp4 file contains codecs which are compatible with webm. otherwise he would need to perform a lossy reencode to codecs which are compatible with webm
taltamir
CC BY-SA 4.0
2024-09-12T00:28:58.560Z
2024-09-22T17:23:02.363Z
2024-09-22T17:23:02.363Z
taltamir
<p>What is the best way to convert a <code>mp4</code> file to <code>webm</code> without quality loss (using <code>vp8</code> or <code>vp9</code>) with ffmpeg?</p>

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

<p><code>ffmpeg -i in.mp4 -crf 10 -b:v 1M out.webm</code> </p>

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

<p>I also noticed that if you specify a much larger value for the target bitrate than the bitrate of the input (here for example <code>-b:v 100M</code>), 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.</p>

<p>How would you choose the crf value and why?</p>

<p>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?</p>

CC BY-SA 3.0
2016-10-15T18:22:04.973Z
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
CC BY-SA 3.0
2016-10-15T19:21:22.133Z
@Mulvya: Does bitrate 0 mean that there is no limit? I didn't find this in the man page.
student
CC BY-SA 3.0
2016-10-17T03:14:31.083Z
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
CC BY-SA 3.0
2016-10-17T11:57:38.567Z
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
CC BY-SA 3.0
2016-10-17T12:03:35.093Z
If you omit it, it defaults to 200k.
Gyan
CC BY-SA 3.0
2016-10-17T12:14:52.557Z
@Mulvya. Thanks for the Info. I also cannot find this one in the man page. Is there any other reference manual for ffmpeg which covers this default value?
student
CC BY-SA 3.0
2016-10-17T12:33:21.700Z
[Link](https://www.ffmpeg.org/ffmpeg-codecs.html#Codec-Options) for 200k (see first option). For WebM b:v 0, see this [page](https://trac.ffmpeg.org/wiki/Encode/VP9).
Gyan
<ffmpeg><vp9><lossless>
Convert mp4 to webm without quality loss with ffmpeg
student
# Convert mp4 to webm without quality loss with ffmpeg

(Asked by: username_0 on 2016-10-15)

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?

**Tags:** ffmpeg, vp9, lossless

> **Comments:**
> **username_1**: 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  
> **username_0**: @Mulvya: Does bitrate 0 mean that there is no limit? I didn't find this in the man page.  
> **username_1**: 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.  
> **username_0**: 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.  
> **username_1**: If you omit it, it defaults to 200k.  
> **username_0**: @Mulvya. Thanks for the Info. I also cannot find this one in the man page. Is there any other reference manual for ffmpeg which covers this default value?  
> **username_1**: [Link](https://www.ffmpeg.org/ffmpeg-codecs.html#Codec-Options) for 200k (see first option). For WebM b:v 0, see this [page](https://trac.ffmpeg.org/wiki/Encode/VP9).  

---

## 3 answers

### Answer by username_2 on 2019-08-15. Score: 40

Answer
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

Notes

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

We discard the video using /dev/null because the first pass's only purpose is to generate a log file of statistics.


mp42webm shell script
To save typing in the future, this can be put in a UNIX shell script:
#!/bin/sh -xe
ffmpeg -i "$1" -b:v 0 -crf 30 -pass 1 -an -f webm -y /dev/null
ffmpeg -i "$1" -b:v 0 -crf 30 -pass 2 "${1%.mp4}.webm"

Usage: mp42webm filename.mp4. 
Creates filename.webm.
Explanation:
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.

> **Comments:**
> **username_3**: `/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.  
> **username_2**: 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.  
> **username_4**: 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"  
> **username_5**: 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?  
> **username_6**: Hmm. That didn't work. Second command failed: "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"  
> **username_7**: `File '/dev/null' already exists. Overwrite ? [y/N]` so I will switch it to /tmp/deleteme.webm  
> **username_2**: @reducingactivity Thanks for letting me know that ffmpeg changed the default behaviour. It is safe to answer 'y" when writing to /dev/null as it is a fake file that ignores anything written to it. I've updated my answer to include the `-y` flag so that people won't be asked "Overwrite?".  
> **username_8**: I think it is silly that 2 passes cannot be accomplished with one command. When I see two separate commands like this it makes me worry that the 2nd command will not even take into consideration what is accomplished by the first command.  
> **username_9**: Would this work going the other way? ```ffmpeg  -i input.webm  -lossless 1  output.mp4```  
> **username_2**: Good question. The answer is no, lossless mode is a feature of webm.  

---

### Answer by username_10 on 2020-07-04. Score: 1

On Linux I use [optimizeVideo](https://gitlab.com/es20490446e/optimizeVideo), which is a wrapper around ffmpeg that automatically detects those settings according to [Google's recommendations](https://developers.google.com/media/vp9/settings/vod/).

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

[![Logo](https://i.sstatic.net/BQMCT.png)](https://i.sstatic.net/BQMCT.png)


---

### Answer by username_11 on 2024-09-12. Score: -1

mp4 and webm are container formats. think of them as boxes that contain within them various video, audio, subtitle, chapter info, etc files.
if all the streams within the source mp4 container file are compatible with webm container format then it can be losslessly converted to webm, this is called remuxing (aka stream copy). This process simply copies the individual streams from one container to another without changing them in any way.
which is an extremely quick process and also lossless, has a trivial effect on file size (from mp4 to webm you save a bit of space). There is no generational quality loss due to not modifying the video and audio streams.
https://ffmpeg.org/ffmpeg.html#Stream-copy
ffmpeg -i input.mp4 -c copy output.webm

I have tested the above command myself and it works great. if the mp4 container is using streams that are NOT compatible with webm. (for example h264 video. or srt subtitles). Then you cannot remux / stream copy it.
If one of the streams you are trying to pass to webm is unsupported it will instead error out and inform you that:

Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.

you would have to resort to re-encoding the unsupported stream. if you are re-encoding the video it is a lengthy process that will cause a variable hit to the image quality
near negligible is possible with the right settings and quality input. although doing so might take a long time and a lot of space. depending on the exact details of input and output codec and configuration. furthermore each time you convert via re-encoding you suffer generational loss. so even negligible losses add up to serious losses if you do it over and over.
technically, you can re-encode it into a lossless format or lossless setting. But doing so will result in obscenely large files. Making them impractical for many uses. realistically you won't be wanting to do that.

> **Comments:**
> **username_12**: Your post doesn't seem to answer the question  
> **username_11**: @username_12 please reread. it clearly answers the question. He wanted to losslessly convert mp4 to webm using ffmpeg. I gave him the command to do so, being `ffmpeg -i input.mp4 -c copy output.webm` with the caveat that it can only be losslessly converted if the source mp4 file contains codecs which are compatible with webm. otherwise he would need to perform a lossy reencode to codecs which are compatible with webm  

---

