← 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.
Inputs
One optional dictionary parameter (default {}) with two optional MediaTrackConstraintSet members. Three implementation rules from user_media_element_constraints.cc:
- 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. - Member backfill. Whichever of
video/audioyou omit is stored as an emptyMediaTrackConstraintsrather than left absent. Consequence: the provider's “No video/audio constraints set”NotSupportedErrorbranches are not reachable through the JS surface, and passing the “wrong” member (e.g.audioon a<camera>) does not throw — the element still requests its own kind with the (backfilled, empty) constraints. - Bare-scalar sanitizer. Each member is filtered to plain scalar values only —
exact/min/max/idealobject 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 anOverconstrainedErrorfrom your configuration.
| Group | Properties kept (bare form only) |
|---|---|
| Video | width, height (long) · aspectRatio, frameRate (double) · facingMode, resizeMode (string or string[]) |
| Audio | channelCount, sampleSize, sampleRate (long) · latency (double) · autoGainControl, echoCancellation, noiseSuppression, voiceIsolation (boolean) |
| Shared | deviceId, groupId (string or string[]) |
| Dropped | Any property in {exact}/{min}/{max}/{ideal} object form; any property not listed above |
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.
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.
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.
Lifecycle
- Before first call: no stored constraints; an activation requests with empty default constraints for the element's kind.
- First call: members sanitized and backfilled, stored,
did_set_constraints_set. - Later calls: no-ops.
- At activation: the stored (or default) constraints build the kind-scoped capture request; they persist across attempts — a failed attempt does not clear them.
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 / runtime | Support | Notes |
|---|---|---|
| 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 / Safari | Not supported | No signal on the ChromeStatus record |
| BCD / MDN | No entries | No BCD files; both MDN interface pages 404 (2026-07-28) |
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.