Mediadevices Api

navigator.mediaDevices.getUserMedia() returns a live MediaStream from the camera or microphone. Feed it to a video element, pull frames to canvas, or pipe it anywhere. Green tier, HTTPS-only, permission-required.

June 10, 20263 min read15 / 17

The browser has been able to access a webcam since 2013. navigator.mediaDevices.getUserMedia() is the call that connects JavaScript to the camera -- and the MediaStream it returns is more versatile than most developers realize.

This is green tier. Chrome, Firefox, Safari, and Edge all support it on desktop and mobile.

Getting a Stream

JavaScript
const stream = await navigator.mediaDevices.getUserMedia({ video: true, // request camera audio: false // skip microphone })

The constraints object controls what you get:

  • video: true -- any available camera, browser decides which
  • video: { facingMode: 'environment' } -- rear camera (phone back)
  • video: { facingMode: 'user' } -- front camera (selfie side)
  • video: { width: 1280, height: 720 } -- request resolution (not guaranteed)

The call is async and triggers the permission model. On denial it throws DOMException: NotAllowedError.

Displaying the Stream

JavaScript
const videoEl = document.getElementById('preview') videoEl.srcObject = stream // assign stream directly videoEl.play() // start rendering

srcObject accepts a MediaStream directly -- no blob URL needed. The video element renders live camera output continuously.

Extracting Frames for Processing

The stream does not have to go to a video element. Pull individual frames to a canvas:

JavaScript
const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') function captureFrame() { canvas.width = videoEl.videoWidth canvas.height = videoEl.videoHeight ctx.drawImage(videoEl, 0, 0) return canvas // now pass to BarcodeDetector, run filters, etc. }

This is the bridge to the Shape Detection API: capture a frame, pass it to BarcodeDetector.detect(), and read the QR code. No need to upload anything -- the image processing stays on-device.

MediaDevices API: getUserMedia flow, stream → video element or frame extraction ExpandMediaDevices API: getUserMedia flow, stream → video element or frame extraction

Stopping the Stream

An open camera stream keeps the OS recording indicator active and drains battery.

JavaScript
function stopStream(stream) { stream.getTracks().forEach(track => track.stop()) }

A MediaStream has one or more tracks (video, audio). Calling track.stop() releases the camera or microphone. The video element goes blank.

Advanced Camera Control (PTZ)

Chromium supports Pan, Tilt, and Zoom on cameras that expose those controls:

JavaScript
const [track] = stream.getVideoTracks() const capabilities = track.getCapabilities() if (capabilities.zoom) { await track.applyConstraints({ advanced: [{ zoom: 3 }] // 3x zoom if the camera supports it }) }

getCapabilities() returns what the current hardware supports. PTZ is Chromium only -- Safari and Firefox do not expose these controls.

Security Rules

HTTPS only. navigator.mediaDevices is undefined on HTTP origins. The API does not exist, let alone prompt for permission.

Permission is sticky. The permission model applies here the same way it does for geolocation. Denial is permanent until the user manually resets it in browser settings.

The browser also stops or mutes streams automatically when the page is hidden -- you cannot silently record in the background.

Augmented reality takes the camera stream further: instead of displaying it in a video element, WebXR and AR overlay virtual objects on top of it.

The Essentials

  1. await navigator.mediaDevices.getUserMedia({ video: true }) returns a MediaStream. Assign to videoEl.srcObject to display live.
  2. Constraints control facingMode (front/rear) and resolution -- hardware is the hard limit, constraints are a request.
  3. Always stop tracks when done: stream.getTracks().forEach(t => t.stop()) releases the camera.
  4. Frames extracted via ctx.drawImage(videoEl, ...) can be passed directly to BarcodeDetector.detect() or any image pipeline.
  5. HTTPS-only. PTZ camera control is Chromium only. Core stream API is green tier everywhere.

Further Reading