Web APIs Cheatsheet

Media Devices

Use this Web APIs reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

getUserMedia — Camera and Microphone

// Basic camera + mic
const stream = await navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true,
});
video.srcObject = stream;
await video.play();

// Advanced constraints
const stream = await navigator.mediaDevices.getUserMedia({
  video: {
    width:  { ideal: 1280, max: 1920 },
    height: { ideal: 720,  max: 1080 },
    facingMode: 'user',           // 'user' | 'environment' (front/back cam)
    frameRate: { ideal: 30, max: 60 },
    deviceId: { exact: selectedDeviceId },
  },
  audio: {
    sampleRate: 48000,
    channelCount: 1,
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true,
    deviceId: micDeviceId,
  },
});

Stopping the Stream

// Stop all tracks
stream.getTracks().forEach(track => track.stop());

// Stop specific track
stream.getVideoTracks().forEach(t => t.stop());
stream.getAudioTracks().forEach(t => t.stop());

MediaStream and MediaStreamTrack

stream.id;                        // unique string
stream.active;                    // true if any track is live
stream.getTracks();               // MediaStreamTrack[]
stream.getVideoTracks();
stream.getAudioTracks();
stream.getTrackById(id);
stream.addTrack(track);
stream.removeTrack(track);
stream.clone();                   // shallow clone (tracks shared)

// Events
stream.addEventListener('addtrack',    e => e.track);
stream.addEventListener('removetrack', e => e.track);
const track = stream.getVideoTracks()[0];
track.kind;          // 'video' | 'audio'
track.label;         // device label (e.g. 'FaceTime HD Camera')
track.id;
track.enabled;       // false = mute/pause (stream still flows, just black/silent)
track.muted;         // true when track source is muted by hardware/OS
track.readyState;    // 'live' | 'ended'

track.stop();        // end the track
track.clone();

// Apply constraints on live track
await track.applyConstraints({ width: 640, height: 480 });
track.getConstraints();      // last applied constraints
track.getCapabilities();     // browser support ranges
track.getSettings();         // current actual values

// Events
track.addEventListener('mute',   () => {});
track.addEventListener('unmute', () => {});
track.addEventListener('ended',  () => {});

getDisplayMedia — Screen Sharing

const stream = await navigator.mediaDevices.getDisplayMedia({
  video: {
    displaySurface: 'monitor', // 'monitor' | 'window' | 'browser'
    frameRate: { max: 30 },
    width: { ideal: 1920 },
  },
  audio: true,          // system audio (where supported)
  selfBrowserSurface: 'exclude',
  systemAudio: 'include',
  monitorTypeSurfaces: 'include',
});

// Screen share ended by user
stream.getVideoTracks()[0].addEventListener('ended', stopSharing);

enumerateDevices — List Devices

const devices = await navigator.mediaDevices.enumerateDevices();
// Returns MediaDeviceInfo[]
for (const d of devices) {
  d.kind;       // 'audioinput' | 'audiooutput' | 'videoinput'
  d.label;      // empty string until permission granted
  d.deviceId;   // unique id (changes if cookies cleared)
  d.groupId;    // same for physically connected devices
}

const cameras = devices.filter(d => d.kind === 'videoinput');
const mics    = devices.filter(d => d.kind === 'audioinput');
const speakers = devices.filter(d => d.kind === 'audiooutput');

// Device change
navigator.mediaDevices.addEventListener('devicechange', async () => {
  const updated = await navigator.mediaDevices.enumerateDevices();
});

Capture Photo from Camera

const canvas = document.createElement('canvas');
canvas.width  = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
const blob = await new Promise(res => canvas.toBlob(res, 'image/jpeg', 0.9));

ImageCapture API

const track = stream.getVideoTracks()[0];
const capture = new ImageCapture(track);

const blob  = await capture.takePhoto({ fillLightMode: 'flash' });
const frame = await capture.grabFrame();  // ImageBitmap of current frame
const capabilities = await capture.getPhotoCapabilities();
// capabilities.fillLightMode, .imageWidth, .imageHeight, .redEyeReduction, …
await capture.setOptions({ zoom: 2, torch: true });

MediaRecorder — Record Audio / Video

const recorder = new MediaRecorder(stream, {
  mimeType: 'video/webm;codecs=vp9,opus',   // check with MediaRecorder.isTypeSupported()
  audioBitsPerSecond: 128000,
  videoBitsPerSecond: 2500000,
  bitsPerSecond: 2628000,                    // overrides the two above
});

const chunks = [];
recorder.addEventListener('dataavailable', e => {
  if (e.data.size > 0) chunks.push(e.data);
});
recorder.addEventListener('stop', () => {
  const blob = new Blob(chunks, { type: recorder.mimeType });
  const url  = URL.createObjectURL(blob);
  videoEl.src = url;
});

recorder.start();           // start without slicing
recorder.start(1000);       // fire 'dataavailable' every 1000 ms

recorder.pause();
recorder.resume();
recorder.stop();            // fires 'dataavailable' + 'stop'
recorder.requestData();     // force 'dataavailable' immediately

recorder.state;             // 'inactive' | 'recording' | 'paused'
recorder.mimeType;
recorder.stream;

recorder.addEventListener('start',   e => {});
recorder.addEventListener('pause',   e => {});
recorder.addEventListener('resume',  e => {});
recorder.addEventListener('stop',    e => {});
recorder.addEventListener('error',   e => e.error);

// Check support
MediaRecorder.isTypeSupported('video/mp4');
MediaRecorder.isTypeSupported('video/webm;codecs=vp9');

Web Audio API

const ctx = new AudioContext({ latencyHint: 'interactive', sampleRate: 48000 });
ctx.state;              // 'suspended' | 'running' | 'closed'
await ctx.resume();     // must be called in user gesture context
await ctx.suspend();
await ctx.close();
ctx.currentTime;        // high-precision timestamp in seconds
ctx.sampleRate;         // samples per second
ctx.destination;        // AudioDestinationNode (speakers)
ctx.listener;           // AudioListener (for 3D audio)

Common Audio Nodes

// OscillatorNode — generates a tone
const osc = ctx.createOscillator();
osc.type = 'sine';     // 'sine' | 'square' | 'sawtooth' | 'triangle' | 'custom'
osc.frequency.value = 440;
osc.start();  osc.stop(ctx.currentTime + 1);

// GainNode — volume control
const gain = ctx.createGain();
gain.gain.value = 0.5;

// BiquadFilterNode
const filter = ctx.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 800;

// AnalyserNode — visualizations
const analyser = ctx.createAnalyser();
analyser.fftSize = 2048;
const buffer = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(buffer);
analyser.getByteTimeDomainData(buffer);  // waveform

// Connect graph: source → gain → analyser → destination
osc.connect(gain).connect(analyser).connect(ctx.destination);

// MediaStreamSource — from getUserMedia
const source = ctx.createMediaStreamSource(stream);
source.connect(analyser).connect(ctx.destination);

// MediaElementSource — from <audio>/<video>
const elSource = ctx.createMediaElementSource(audioEl);
elSource.connect(gain).connect(ctx.destination);

// Buffer (preloaded sound)
const res = await fetch('/sound.mp3');
const rawBuffer = await res.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(rawBuffer);
const player = ctx.createBufferSource();
player.buffer = audioBuffer;
player.loop = true;
player.connect(ctx.destination);
player.start(0);     // start now
player.start(ctx.currentTime + 2, 0.5, 2); // start in 2 s, offset 0.5 s, duration 2 s
player.stop();

AudioParam Scheduling

gain.gain.setValueAtTime(0, ctx.currentTime);
gain.gain.linearRampToValueAtTime(1, ctx.currentTime + 0.5);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 2);
gain.gain.setTargetAtTime(0, ctx.currentTime, 0.3);     // time constant
gain.gain.setValueCurveAtTime([0, 0.5, 1, 0.5, 0], ctx.currentTime, 2);
gain.gain.cancelScheduledValues(ctx.currentTime);
gain.gain.cancelAndHoldAtTime(ctx.currentTime);

HTMLMediaElement (audio / video)

const video = document.querySelector('video');

// Playback
video.play();           // Returns Promise
video.pause();
video.load();           // reload source
video.currentTime = 30; // seek to 30 s
video.playbackRate = 1.5;
video.defaultPlaybackRate = 1;
video.volume = 0.8;     // 0–1
video.muted = true;
video.loop = true;

// Properties
video.duration;         // total seconds (NaN before metadata)
video.currentTime;
video.paused;           // boolean
video.ended;
video.seeking;
video.readyState;       // 0=HAVE_NOTHING … 4=HAVE_ENOUGH_DATA
video.networkState;     // 0=EMPTY, 1=IDLE, 2=LOADING, 3=NO_SOURCE
video.buffered;         // TimeRanges
video.played;           // TimeRanges
video.seekable;         // TimeRanges
video.videoWidth; video.videoHeight; // intrinsic dimensions

// Source
video.src = '/video.mp4';
video.currentSrc;       // active source
video.canPlayType('video/mp4'); // '' | 'maybe' | 'probably'

// Tracks
video.textTracks;       // TextTrackList
video.audioTracks;      // AudioTrackList
video.videoTracks;      // VideoTrackList

// Fullscreen
video.requestFullscreen({ navigationUI: 'hide' });

// Picture-in-Picture
await video.requestPictureInPicture();
await document.exitPictureInPicture();
document.pictureInPictureElement;
document.pictureInPictureEnabled;

setSinkId — Audio Output Device

// Route audio to a specific speaker
await audioEl.setSinkId(deviceId);
audioEl.sinkId; // current output device id

Permissions

const cam  = await navigator.permissions.query({ name: 'camera' });
const mic  = await navigator.permissions.query({ name: 'microphone' });
const screen = await navigator.permissions.query({ name: 'display-capture' });
cam.state;  // 'granted' | 'denied' | 'prompt'
cam.addEventListener('change', () => console.log(cam.state));