MediaDeviceInfo: How the Browser Describes Webcam Cameras and Microphones
What MediaDeviceInfo is, what its fields mean, why labels are often blank, and how to use it to find and select a webcam's built-in microphone.
MediaDeviceInfo is the Web API object a browser uses to describe a single media device available to a page: a camera, a microphone, or an audio output such as speakers or headphones. A page gets a list of these objects by calling navigator.mediaDevices.enumerateDevices(). For webcam audio, this is how a page discovers the microphone built into a webcam and selects it for speech capture. There are two important limits. First, MediaDeviceInfo describes what a device is and how to address it, not how good it sounds. Second, browsers usually hide device names and stable identifiers until the user has granted camera or microphone permission.
What a MediaDeviceInfo object contains
The interface exposes four read-only properties and one method, toJSON(), which returns a plain serializable copy of those properties. The properties are documented in the Media Capture and Streams specification and are available in current major browsers.
| Property | What it holds | Relevance to webcam audio |
| deviceId | An identifier for the device, unique to the current site (origin) | Passed to getUserMedia() to capture from that exact microphone |
| groupId | An identifier shared by devices that belong to the same physical hardware | Can link a webcam's camera to its built-in microphone |
| kind | One of audioinput, audiooutput or videoinput | audioinput entries are microphones; videoinput entries are cameras |
| label | A human-readable name, such as the product name reported by the system | Lets users recognise the webcam mic in a picker; empty without permission |
Input devices may also be returned as InputDeviceInfo, a subtype that adds getCapabilities(). This method can report the ranges a device supports, but browser support for it is inconsistent, so code should check that it exists before calling it.
Listing devices
async function listDevices() {
// Requesting access first lets the browser reveal labels and stable IDs
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
const devices = await navigator.mediaDevices.enumerateDevices();
stream.getTracks().forEach(track => track.stop());
for (const d of devices) {
console.log(d.kind, d.label, d.deviceId, d.groupId);
}
return devices;
}
enumerateDevices() returns a promise that resolves to an array of MediaDeviceInfo objects. navigator.mediaDevices exists only in a secure context, meaning a page served over HTTPS or from localhost. On a plain HTTP page the API is unavailable.
Why labels and IDs are often blank
Device names and identifiers can be used to fingerprint a visitor, so browsers restrict them. Until the page has been granted camera or microphone permission, label is typically an empty string. deviceId and groupId may also be empty, and the list may be reduced to a placeholder entry for each kind. In practice, a device picker that shows real microphone names should first request access with getUserMedia() and then enumerate devices again. The exact pre-permission behaviour differs between browsers, so code should not assume a particular number of entries or non-empty IDs.
Finding the microphone built into a webcam
Because groupId is meant to be shared by devices on the same physical hardware, the usual approach is to find the camera's videoinput entry and then look for an audioinput entry with the same groupId.
function findWebcamMic(devices, cameraDeviceId) {
const camera = devices.find(d => d.kind === 'videoinput' && d.deviceId === cameraDeviceId);
if (!camera || !camera.groupId) return null;
return devices.find(d =>
d.kind === 'audioinput' &&
d.groupId === camera.groupId &&
d.deviceId !== 'default' &&
d.deviceId !== 'communications'
) || null;
}
Treat this as a best-effort match, not a guarantee. Whether a webcam's camera and microphone share a groupId depends on how the operating system and browser report the hardware. Some setups place them in different groups. If no match is found, matching on label text is a common fallback, but it is a heuristic and can fail when names differ. Chromium-based browsers can also list extra audioinput entries with the IDs default and communications. These entries point to whichever real device the system has assigned to that role, so the same microphone can appear more than once. The function above skips them for that reason. When automatic matching is uncertain, the most reliable option is to let the user choose from the labelled list.
Selecting the microphone for speech capture
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
deviceId: { exact: mic.deviceId },
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
}
});
const settings = stream.getAudioTracks()[0].getSettings();
console.log(settings.deviceId, settings.sampleRate, settings.channelCount);
With exact, the call fails with an OverconstrainedError if that microphone is unavailable. With ideal instead of exact, the browser may fall back to another microphone. Use exact when capturing from the wrong device would be worse than failing, for example when a user has explicitly chosen a microphone.
The three processing constraints shape the captured speech. echoCancellation tries to remove sound from the speakers that leaks back into the microphone. noiseSuppression reduces steady background noise. autoGainControl adjusts the level automatically. These features generally help in live calls. For recordings where the natural sound of the voice matters, some developers turn them off, but whether that improves results depends on the room and the microphone. The browser may also apply them differently from what was requested, so check getSettings() to see what actually took effect.
A deviceId generally stays the same for a given site across visits, so a saved choice can be reused. It can change if the user clears site data, and the device may be unplugged. Code that restores a saved microphone should handle a missing device and listen for the devicechange event on navigator.mediaDevices so the list can be refreshed when hardware is connected or removed.
What MediaDeviceInfo cannot tell you about voice quality
MediaDeviceInfo has no fields for microphone sensitivity, frequency response, pickup pattern, noise floor or supported sample rates. Two webcams with identical-looking entries can sound very different. The track returned by getUserMedia() can report the active settings, such as sampleRate and channelCount, through getSettings(). Not every browser fills in every field, and these values describe the capture configuration, not how clear the speech sounds. Judging voice quality requires recording and listening, or measuring the captured audio. No such measurements are available for this article, so no claims are made about how particular webcam microphones perform.
Practical checklist
- Serve the page over HTTPS or from localhost so navigator.mediaDevices is available.
- Request microphone (and camera) permission before relying on label, deviceId or groupId.
- Filter for kind audioinput to list microphones.
- Try matching the webcam's microphone by groupId, but let the user confirm or override the choice.
- Ignore or clearly mark the default and communications entries in Chromium-based browsers.
- Capture with deviceId set to exact when the chosen microphone must be used.
- Check getSettings() to confirm the device and processing that actually took effect.
- Refresh the device list when the devicechange event fires.