← Capability elements: <camera> and <microphone>

v153 · html · method + dictionary reference

setConstraints() / HTMLMediaStreamConstraints

The configuration channel for the capture request a <camera> or <microphone> element makes: call setConstraints() with an HTMLMediaStreamConstraints dictionary (video and audio MediaTrackConstraintSet members) before the user interacts. The shipping contract has three non-obvious rules — first-call-wins, member backfill, and a bare-scalar sanitizer — all derived from the implementation below.

Syntax

// Shipping Chromium IDL (partial mixin applying to all three capability elements):
undefined setConstraints(optional HTMLMediaStreamConstraints constraints = {});

dictionary HTMLMediaStreamConstraints {
  MediaTrackConstraintSet video;
  MediaTrackConstraintSet audio;
};

// Usage on the single-capability elements (use YOUR element's member):
document.querySelector("camera").setConstraints({
  video: { width: 1280, facingMode: "environment" }
});
document.querySelector("microphone").setConstraints({
  audio: { echoCancellation: true, noiseSuppression: true }
});

// Draft spec IDL (diverges — see overview "spec vs shipping"):
//   undefined setConstraints(optional MediaTrackConstraintSet constraints = {});

Chromium ships the method and dictionary in user_media_element_constraints.idl as a partial on the shared HTMLMediaCaptureElementBase mixin — so <camera> and <microphone> take the same two-member dictionary as <usermedia>, not the draft's bare MediaTrackConstraintSet. The MediaTrackConstraintSet members accept the same constraint properties as getUserMedia(), defined by Media Capture and Streams.

Source: Chromium user_media_element_constraints.idl; Specification — setConstraints (draft signature).

Inputs

One optional dictionary parameter (default {}) with two optional MediaTrackConstraintSet members. Three implementation rules from user_media_element_constraints.cc:

  1. First call wins. A did_set_constraints_ flag makes every call after the first a silent no-op — there is no error and no way to reconfigure; put all configuration in one call, before the user interacts.
  2. Member backfill. Whichever of video/audio you omit is stored as an empty MediaTrackConstraints rather than left absent. Consequence: the provider's “No video/audio constraints set” NotSupportedError branches are not reachable through the JS surface, and passing the “wrong” member (e.g. audio on a <camera>) does not throw — the element still requests its own kind with the (backfilled, empty) constraints.
  3. Bare-scalar sanitizer. Each member is filtered to plain scalar values only — exact/min/max/ideal object forms are dropped property-by-property (see the table below). A property present only in object form disappears entirely, so the element cannot hard-fail on an OverconstrainedError from your configuration.
Sanitizer — what survives SanitizeTrackConstraints()
GroupProperties kept (bare form only)
Videowidth, height (long) · aspectRatio, frameRate (double) · facingMode, resizeMode (string or string[])
AudiochannelCount, sampleSize, sampleRate (long) · latency (double) · autoGainControl, echoCancellation, noiseSuppression, voiceIsolation (boolean)
ShareddeviceId, groupId (string or string[])
DroppedAny property in {exact}/{min}/{max}/{ideal} object form; any property not listed above
Source: Chromium user_media_element_constraints.cc — setConstraints (first-call-wins, backfill) and SanitizeTrackConstraints.

Outputs

No return value (undefined) and no observable effect on first call other than storing the sanitized constraints for the next activation. The stored constraints shape the capture request built at click time: the provider constructs a kind-scoped request — video-only for <camera> (using the video member), audio-only for <microphone> (using the audio member) — regardless of what the other member holds.

Source: Chromium user_media_request_provider_impl.cc — kind-scoped request construction.

Errors

The method itself never throws for constraint content: malformed member values are dropped by the sanitizer, and repeat calls are silently ignored. Capture-time failures surface later through the element's error event, not from this call. Calling setConstraints() on an element whose runtime feature is off is impossible (the interface doesn't exist); calling it on a fallback-rendered unknown element in an unsupported engine is a TypeError (no such function) — feature-detect first.

Source: Chromium user_media_element_constraints.cc.

Context

Available on <camera> and <microphone> element instances in a Window context. Call it any time before activation; because the first call wins, the practical contract is “configure once, immediately after obtaining the element”. The method exists on the same shared mixin partial as stream, so its presence tracks the CameraAndMicrophoneElements feature.

Source: Chromium user_media_element_constraints.idl.

Lifecycle

  1. Before first call: no stored constraints; an activation requests with empty default constraints for the element's kind.
  2. First call: members sanitized and backfilled, stored, did_set_constraints_ set.
  3. Later calls: no-ops.
  4. At activation: the stored (or default) constraints build the kind-scoped capture request; they persist across attempts — a failed attempt does not clear them.
Source: Chromium user_media_element_constraints.cc; Chromium user_media_request_provider_impl.cc.

Examples

const cam = document.querySelector("camera");
const mic = document.querySelector("microphone");

// Configure once, before the user clicks:
cam.setConstraints({ video: { width: 1280, height: 720, facingMode: "environment" } });
mic.setConstraints({ audio: { echoCancellation: true, noiseSuppression: true, sampleRate: 48000 } });

// WRONG — silently ignored (first call already won):
// cam.setConstraints({ video: { width: 640 } });

// WRONG expectation — object-form constraints are dropped property-by-property:
// cam.setConstraints({ video: { width: { exact: 1280 } } });
//   → stored as video: {} (width removed; no OverconstrainedError possible)

// Harmless but pointless — wrong member is stored then ignored for the request:
// mic.setConstraints({ video: { width: 1280 } });
//   → microphone still requests audio with empty constraints
Source: Chromium user_media_element_constraints.cc.

Compatibility

Engine / runtimeSupportNotes
Chrome / Edge (desktop)153 (listing)Same availability as the elements; trunk flag status caveat in the overview table. Behavior above is the shared modules/mediastream implementation also used by <usermedia> (151+)
Chrome (Android)153 (listing)WebView: explicit unknown (see overview)
Firefox / SafariNot supportedNo signal on the ChromeStatus record
BCD / MDNNo entriesNo BCD files; both MDN interface pages 404 (2026-07-28)
Source: ChromeStatus API feature record.

Security and privacy

The sanitizer is also a privacy control: by dropping exact/min/max/ideal forms, the elements cannot be used to hard-probe device capabilities (a failed exact constraint would reveal device characteristics) — the same anti-fingerprinting stance as getUserMedia()'s permission-gated device information. deviceId/groupId survive in bare form but remain subject to the permission-mediated capture flow: the browser still runs its own prompt/recovery UX before any capture starts.

Source: Chromium user_media_element_constraints.cc — SanitizeTrackConstraints; Explainer — privacy considerations.