The page asks for { audio: true }. Your browser answers with echo cancellation,
noise suppression and automatic gain.
Short answer: this converter's Record button asks the browser for the microphone with
getUserMedia({ audio: true }) and nothing else. Every other setting is left
to the browser, and in Chrome that means echo cancellation, noise suppression and automatic gain
control all switched on - the same chain used for voice calls, never adjusted for music. The
recording is written as Opus inside WebM at 48 kHz mono, about 80 kbps in
my measurement. The 80 MB limit is checked against that compressed file, so the microphone path allows
about 140 minutes where a stereo WAV upload allows 7.9 minutes.
Everything here is read out of this page's own source or measured by me while it ran. Two of the numbers come from a browser microphone that was not a real microphone - I say exactly which, and why, further down.
The microphone code is short enough to read in full. Pressing the button does this:
navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
var chunks = [];
var mr = new MediaRecorder(stream);
...
mr.onstop = function () {
stream.getTracks().forEach(function (t) { t.stop(); });
var blob = new Blob(chunks, { type: mr.mimeType || 'audio/webm' });
if (blob.size > MAX_BYTES) { /* dropped */ }
...
fr.readAsArrayBuffer(blob);
};
mr.start();
});
Then the recording is handed to the same decode() the file path uses, and from there it is the
identical pipeline: decode, average to one channel, resample to 16 kHz, run YIN. Nothing downstream knows or
cares whether the audio arrived from a file or from a microphone.
Four things in that snippet are worth naming.
echoCancellation, no noiseSuppression, no autoGainControl.mimeType, no
audioBitsPerSecond.MAX_BYTES is
80 × 1024 × 1024 = 83,886,080 bytes, the same cap the file path uses - but applied to a very
different kind of file.stream.getTracks().forEach(t =>
t.stop()) runs on stop, so the recording light should go out.{ audio: true } actually got youI intercepted the page's own call and read back what the track was really running with. Not the defaults I assume, not the documentation - the values from that call, on that track:
| Setting | Value the browser applied | What it is for |
|---|---|---|
echoCancellation | true | Removing speaker output leaking into the mic |
noiseSuppression | true | Suppressing steady background noise |
autoGainControl | true | Levelling loudness automatically |
channelCount | 1 | Mono capture |
sampleRate | 48000 | Hz |
latency | 0.01 | Seconds |
voiceIsolation | false | Isolating a voice from everything else |
I ran this twice, on two separate browser instances, and got identical values both times.
All three of those processors exist because of video calls. Echo cancellation is for speaker output bleeding into a microphone. Noise suppression is tuned to make speech intelligible against steady background noise. Automatic gain control exists so that whoever is speaking is always about the same loudness, whether they lean in or lean back. None of the three was designed with a sustained musical tone in mind, and a musical note is close to the worst case for all of them: it is continuous, it is periodic, and its loudness is usually the thing you are trying to preserve.
The important part is not that these are on. It is that the page never asked for them and
never turned them off. Asking for { audio: true } is asking the browser to decide.
I also read the track's capabilities - the range of values the browser would have accepted. Every one of those three processors can be turned off:
| Capability | Values accepted |
|---|---|
autoGainControl | true, false |
noiseSuppression | true, false |
echoCancellation | true, false, "remote-only", "all" |
voiceIsolation | true, false |
channelCount | min 1, max 2 |
sampleRate | min 44100, max 48000 |
So this is not a browser limitation. The page could have asked for clean audio and did not. I am not claiming the result would have been better if it had - I could not measure that, and I explain why below - but the choice was available and was not taken.
new MediaRecorder(stream) with no options, so the container and codec are whatever the browser
picks. In Chrome that is:
| Property | Measured |
|---|---|
| MIME type chosen | audio/webm;codecs=opus |
| Audio in the file | Opus, 48,000 Hz, mono |
| Bytes per second, melodic take | 10,007 B/s (about 80 kbps) |
| Bytes per second, continuous tone | 15,000 B/s (about 120 kbps) |
I also asked the browser which recording targets it would accept at all. The answer is narrower than most people expect:
| Type | Recordable here? |
|---|---|
audio/webm | yes |
audio/webm;codecs=opus | yes |
audio/mp4 | yes |
audio/mp4;codecs=mp4a.40.2 | yes |
audio/ogg;codecs=opus | no |
audio/wav | no |
audio/mpeg | no |
audio/flac | no |
There is no way to get a lossless recording out of this button. Whatever you play, the converter analyses an Opus decode of it.
Because the cap is applied to the compressed blob, the microphone path buys enormously more time than the file path does. A 13.70-second recording produced 137,103 bytes, which is 10,007 bytes per second. Against 83,886,080 bytes that is 8,383 seconds, or about 140 minutes.
| Input | Bytes per second | What 80 MB holds |
|---|---|---|
| Microphone, Opus, melodic | 10,007 | 139.7 minutes |
| Microphone, Opus, continuous tone | 15,000 | 93.2 minutes |
| WAV, 44.1 kHz stereo | 176,400 | 7.9 minutes |
| MP3, 320 kbps | 40,020 | 34.9 minutes |
The WAV and MP3 rows are carried over from the article on what the limits actually are; the microphone rows are measured here. The practical upshot is that the recording path is not where you will hit the wall. At the analysis speed I measured there - roughly 50 times real time - 140 minutes of audio would take about three minutes to process.
I wanted to know what the microphone path costs you, so I fed the same eight-note melody in twice: once as a
WAV file, once through the Record button. Both runs went all the way through the live page, and I took the
.mid the page actually wrote on each run and read it back.
| As a WAV file | Through the microphone | |
|---|---|---|
| Notes found | 8 | 8 |
| Pitch range | C4 - C5 | C4 - C5 |
| Reported duration | 12.0 s | 13.7 s |
| MIDI file size | 105 bytes | 105 bytes |
The pitches survived intact. The note start times drifted by 0 to 31 milliseconds - the MIDI tick here is 1.04 ms, and the detector's own frame hop is 16 ms, so most of that drift is a single frame and the worst case is two. The velocities did not survive intact:
| Note | Level in the source | Velocity, WAV | Velocity, microphone |
|---|---|---|---|
| C4 | 0.03 | 57 | 57 |
| D4 | 0.05 | 69 | 58 |
| E4 | 0.08 | 86 | 72 |
| F4 | 0.12 | 100 | 93 |
| G4 | 0.20 | 100 | 100 |
| A4 | 0.30 | 100 | 100 |
| B4 | 0.45 | 100 | 100 |
| C5 | 0.60 | 100 | 100 |
The quiet half of the melody came back 7 to 14 steps softer. The loud half is identical, and that is not reassuring - it is identical because velocity saturates at 100 well before the loud end, a flattening that is documented in how to check whether a conversion is correct. So the microphone path did not damage the top of the range; it had nowhere left to damage.
I want to be precise about what this table does and does not show. Something in the microphone path cost the quiet notes 7 to 14 velocity steps. I could not determine which part - the browser's processing, the Opus encoding, or the playback level of the input I used. I tried to isolate the browser's contribution and could not get a clean measurement, so I am not attributing it. The number is real; the cause is not established.
getSettings
values are worth re-reading on your own setup rather than assuming they match mine.