Record from a microphone with the browser's call processing off by default, a level meter in real dBFS with a clipping indicator, and a length taken from the audio rather than the clock.
Initializing in your browser…
Turn audio into a waveform image in five styles, exported as PNG or real vector SVG. Reads every channel, shows true level in dBFS, and redraws correctly at any size.
Read text aloud with any voice your system provides, with sentence-by-sentence progress that works even for voices that report no word boundaries, and a reading-time estimate calibrated from the voice you pick.
Generate band-limited test tones, sweeps and noise from 20 Hz to 20 kHz. Up to eight voices, note-name entry, binaural beats, and WAV export rendered from the same oscillators you hear.
You want to record an instrument and have the file sound like what you played.
Input
Microphone fed a 1 kHz tone at exactly -12.04 dBFS - Music (raw) - WAV out
Output
Stereo WAV, tone measured at -11.91 dBFS, meter reading -12.04
Browsers apply echo cancellation, noise suppression and automatic gain to a microphone unless a page turns them off, and this one never did: the same tone came back at -23.14 dBFS forced to mono, 11.10 dB of gain change nobody asked for. Music mode requests the raw signal. The meter now reads peak and RMS in dBFS instead of averaging a byte-scaled spectrum, the page no longer asks for microphone permission on load, and one AudioContext serves the whole session where six recordings used to leave six open.
Record from a microphone with the browser's call processing off by default, so what you play is what you get, and a level meter in real decibels with a clipping indicator. Fed a 1 kHz tone at exactly -12.04 dBFS, the recording came back at -11.91 dBFS: with the processing the browser applies unless asked not to, the same tone came back at -23.14 dBFS in mono.
Voice mode, which keeps the noise suppression that makes speech in a noisy room legible.
Music mode, so the automatic gain does not pump on every note and the capture stays stereo.
Watch the meter, keep peaks near -6 dBFS, and set a maximum length so a forgotten recording does not run for an hour.
The panel prints the sample rate, channel count and processing flags the device actually granted.
A browser recorder is mostly a lifecycle problem rather than a signal processing one, and this pass was about the places the lifecycle leaked.
The biggest thing it was doing was to the audio, silently. getUserMedia enables echo cancellation, noise suppression and automatic gain control unless a page explicitly turns them off, and none of those were exposed. They are designed for a video call, and on anything played or sung they are wrong: measured against a fake microphone fed a 1 kHz tone at exactly -12.04 dBFS, the defaults returned it at -23.14 dBFS and forced the capture to one channel, 11.10 dB of gain change applied without a word. There is now a choice between Music, which asks for the raw signal and stereo, and Voice, which keeps the call processing because for a meeting that is what you want. In Music mode the same tone records at -11.91 dBFS in stereo, and the panel prints the settings the microphone actually granted rather than the ones that were requested.
Opening the page used to raise the microphone permission prompt before anything had been clicked, because the device list was built by calling getUserMedia in a mount effect: measured on load, it had been called twice before the user did anything. Devices are now enumerated without permission, which is allowed, and the labels fill in after the first recording, which is the browser's rule.
A new AudioContext was created for every recording and none were ever closed. After six recordings, six were open, which is the limit Chrome allows before it refuses to make another, so the level meter simply stopped working part-way through a session. One context is now created and reused: after seven recordings, one exists. The microphone stream was also only released by the recorder's stop handler, so leaving the page mid-recording left the microphone open; the cleanup now stops the tracks whatever happened. The blob URL cleanup closed over the first render's value, which was always null, so every recording leaked one.
The level meter was an average of every bin of a byte-scaled magnitude spectrum, which is not a level: it moves with the spectrum of the sound rather than with how loud it is, has no units, and cannot show clipping, which is the one thing a recording meter has to show. It now reads peak and RMS in dBFS from the time domain, holds the peak for a second and a half, and lights when a sample reaches full scale. Against the -12.04 dBFS reference tone it reads -12.04.
The length of a recording was taken by subtracting wall-clock timestamps, because WebM out of MediaRecorder carries no duration in its header. That drifts with anything that stalls the page. The blob is now decoded and its real length used, which agreed with the exported file to the millisecond. The elapsed-time display is computed from timestamps rather than by incrementing a counter, and the maximum-duration limit is checked there, so it keeps working after a pause; the previous resume path installed a bare counter and the limit silently stopped applying for the rest of the take.
Recording is WebM with Opus, which is what MediaRecorder produces. Downloading as WAV, MP3 or OGG converts through ffmpeg compiled to WebAssembly, and WebM is now offered as a fourth option so the original can be kept without a re-encode. WAV is the default. Everything happens in the page; no audio is uploaded.
Because browsers apply call processing to a microphone unless asked not to. Measured on a 1 kHz tone at -12.04 dBFS, the defaults returned it at -23.14 dBFS in mono. Switch Capture processing to Music and it records at -11.91 dBFS in stereo.
For speech, especially in a room with background noise or a speaker playing. Echo cancellation and noise suppression are genuinely good at what they are for; they are only wrong when the thing you are recording is music.
Peaks around -6 dBFS leave room for a louder moment without clipping. The meter shows RMS and a held peak in dBFS and turns red once a sample reaches full scale, which cannot be undone afterwards.
Because it does not need to. Devices can be listed without permission, and the prompt now appears when you actually record. The previous build asked on page load.
In the page only. Nothing is uploaded, and the file exists on your device until you download it or close the tab.
Not directly; browsers do not allow it. If your operating system provides a loopback device that appears as a microphone input, select it in the device list and it will record like any other input.
WAV is the default and is lossless from the decoded recording. MP3 and OGG are smaller. WebM is exactly what the browser recorded, with no conversion at all, which is the fastest and keeps the original Opus stream intact.
Audio is decoded and processed locally with the Web Audio API. Your files are never uploaded to a server.