guide

Microphone Test Guide

Reference for the desktest.net Microphone Test: what it checks, how to read the verdict, and how to fix each failure.

Open the Microphone Test ->

What does the Microphone Test check?

Three steps over MediaDevices and Web Audio. No plugin, no upload. Chrome, Edge, Firefox, Safari, over HTTPS or localhost. Each step must pass before the next:

  1. Browser supports getUserMedia and grants permission. enumerateDevices() counts audioinput entries, then getUserMedia({audio: true}) runs inside the Run-button click handler. After grant, re-enumeration reads labels and reports which input the browser opened.
  2. Microphone is producing real signal. The MediaStream feeds an AudioContext through an AnalyserNode (fftSize 256). Byte time-domain data polled for 5 seconds, RMS per frame, peak and average tracked. Pass requires peak RMS above 0.02. A live VU meter shows it in real time.
  3. User confirms a 3-second playback. MediaRecorder captures the same stream, chunks become a Blob, a Blob URL goes to <audio controls>, you click Yes or No.

When should I run this?

Reading the results

Each step shows a badge: Pending (grey), Running (yellow), Pass (green), Fail (red). On fail the row expands with what the API returned and a numbered checklist.

The verdict panel at the top gives a likely cause and a recommended next step. It reflects the common reason; if wrong for your case, the expanded fix block covers the rest.

Copy Diagnostic Report dumps a plain-text report: user-agent, platform, selected device label and id, device count, peak and average RMS, frame count, recording MIME and size, per-step diagnoses, timestamps. Paste into a ticket.

The level meter in step 2 scales current RMS to a 0-100% bar. Voice peaks at 0.1 to 0.3 on the 0 to 1 scale; a healthy mic pushes the bar at least a third of the way across at normal speaking volume.

Common failures and fixes

The tool produces a named diagnosis for every failure path. In step order:

getusermedia-unsupported: API not available

navigator.mediaDevices.getUserMedia is missing. The API requires a secure context: HTTPS or localhost. Confirm the URL starts with https://. In a kiosk wrapper or Electron shell the host may have stripped the API; open in a standalone browser tab. Update browsers older than 2018.

permission-denied: browser blocked the request

getUserMedia threw NotAllowedError. User clicked Block, the origin has a cached denial, or admin policy blocks mic for this site.

Then the OS layer. Windows: Sound > Recording or Settings, Privacy & security, Microphone; confirm "Microphone access" is on and the browser enabled. macOS: Settings > Privacy & Security > Microphone, browser ticked. The OS toggle sometimes flips off after a Windows feature update.

no-input-device: zero microphones enumerated

enumerateDevices() returned zero audioinput entries, or getUserMedia threw NotFoundError / OverconstrainedError. The OS does not see a mic.

  1. Plug a USB headset, USB mic, or webcam directly into the workstation. Avoid passive USB hubs.
  2. Windows: Sound settings, Input. The legacy Recording tab hides disabled devices (right-click, Show Disabled Devices). Device Manager under "Audio inputs and outputs" for a yellow exclamation.
  3. macOS: Settings, Sound, Input. Confirm an input is selected and its meter moves.
  4. Linux: pactl list short sources should list at least one source.

device-busy: mic is held by another app

getUserMedia threw NotReadableError. Another process has exclusive access. Usual suspects: Teams, Zoom, Slack huddles, OBS, Discord, the Windows Camera app, softphone clients (CXone, RingCentral, Five9, Dialpad). Close them all, check the tray for hidden ones, reload. If it persists, sign out and back in.

silent-signal: mic is reading silence

Step 2 measured peak RMS below 0.02 over 5 seconds. The browser opened a real device but no audio reached the analyser above the noise floor. In order of frequency:

  1. Physical mute switch. Most USB headsets have inline mute (Jabra Evolve, Plantronics Voyager, Poly Blackwire). Lift-the-boom-to-mute is standard on Jabra.
  2. Wrong default input. Windows often switches the default to a docking-station mic or HDMI input after a reboot. Step 1 names what the browser opened; if wrong, fix the OS default and rerun.
  3. OS input level at 0. Raise input volume to about 75%.
  4. USB hub underpowered. A headset on a daisy-chained or unpowered monitor hub can enumerate but drop audio. Plug into a chassis port.
  5. Boom mic rotated away from the mouth. A whisper looks like silence at 0.02.
  6. Wrong cable on a 3.5 mm combo jack. Needs CTIA TRRS; a 3-conductor TRS only carries headphones.

webaudio-unsupported: AudioContext missing

Permission worked but the browser does not expose AudioContext. Crops up on stripped-down kiosk webviews or very old Safari. Update or switch browser.

recording-not-supported: MediaRecorder missing

window.MediaRecorder is not a function. Older Safari ships a partial implementation. Update Safari or use Chrome or Firefox.

recording-error / recording-empty: capture failed mid-flight

MediaRecorder started but errored or produced no chunks. Usually a codec issue or an OS audio service that crashed. Restart the browser. On Windows, services.msc, restart "Windows Audio" and "Windows Audio Endpoint Builder". Try a different browser to isolate codec from device.

playback-unclear: user clicked No on the playback

Recording made it through but you could not understand it. Signal level passed, so the mic is producing audio; the audio is just bad.

  1. Wrong input is the OS default. If step 1 says "Realtek HD Audio" but you wanted "Jabra Evolve 65", change the OS default and rerun.
  2. Mic gain too low. Raise the input level to about 75%.
  3. OS "noise suppression" or "echo cancellation" is chopping the signal. Disable both temporarily.
  4. Hardware fault. Swap mics (built-in laptop, USB headset, webcam) to isolate.
  5. Speaker issue, not mic. If the recording is fine but the speakers crackle, run the Speaker Test.

aborted: diagnostic was cancelled

You clicked Reset, navigated away, or cancelled the playback prompt before answering. Click Run Microphone Test again and let each step finish.

For IT admins

Two layers gate mic access: per-site browser permission and OS privacy switch. Both must allow the browser.

Chrome / Edge. Push via GPO, Intune, or Jamf. AudioCaptureAllowed (boolean) and AudioCaptureAllowedUrls (URL patterns that bypass the prompt). Edge takes the same key under Microsoft\Edge.

Firefox. policies.json with Permissions.Microphone: an Allow array of origins, plus BlockNewRequests: true to suppress the prompt.

Windows. Camera Policy CSP handles webcams (separate path). For mic, AppPrivacy CSP LetAppsAccessMicrophone set to 1, with LetAppsAccessMicrophone_ForceAllowTheseApps listing browser PFNs. Feature updates sometimes reset the user-level toggle; check first if mics die fleet-wide after Patch Tuesday.

Conferencing-app defaults override browser-level defaults. Teams, Zoom, and Webex desktop clients pick their own default input on launch and write it back to the OS. The browser inherits the OS default at the moment getUserMedia resolves, which Teams may have rewritten minutes earlier.

Remote sessions. Citrix CVAD, VMware Horizon, and Microsoft AVD redirect mic input from the thin client; confirm the right HDX, Blast Extreme, or RDP audio policy is in place.

Behind the scenes

getUserMedia({audio: true}) runs inside a click handler so the browser counts it as a user gesture. Pre-permission enumerateDevices() returns empty labels (privacy); the call repeats post-grant, and track.getSettings().deviceId names the input the browser actually opened.

The level meter feeds the stream through createMediaStreamSource() into an AnalyserNode (fftSize 256). Each frame reads getByteTimeDomainData(), converts to -1..+1, computes RMS.

Recording uses MediaRecorder with the browser's default codec (Chrome/Edge webm;opus, Firefox ogg;opus, Safari mp4). Chunks become a Blob, a Blob URL goes to <audio controls>, playback runs from memory. Nothing uploaded; the report stores only MIME and byte size. On reset, completion, or unload the tool stops every track and revokes the Blob URL.