getUserMedia Examples
These examples demonstrate the powerful getUserMedia method, which gives web applications secure access to cameras and microphones. To run getUserMedia, your web page needs to be in a secure context, the page must not be under a Permissions Policy that’s limiting device access, and you need to have user permission at the browser level and, in some cases, at the operating system level. When first run, the browser will prompt for permissions, and you can manage these settings through browser preferences or OS privacy controls.
Originally part of WebRTC, getUserMedia has now become essential for tasks such as video recording, audio recording, taking pictures, and enumerating available devices.
The examples below showcase how getUserMedia enables a range of key scenarios, making it a vital tool for modern web applications.
table of contents
- Example 1: Capture Audio and Video
- Example 2: Stop Device Access
- Example 3: Audio Only Constraint
- Example 4: Video Only Constraint
- Example 5: List Available Devices
- Example 6: Recording a Video Clip (MediaRecorder)
- Example 7: Capture Video + Take a Snapshot
- Example 8: Requesting a Certain Aspect Ratio
- Example 9: Requesting a Portrait Video Stream With facingMode:user
- Example 10: Basic Video Preview
- Example 11: Async/Await + Audio Only
π₯π€ Example 1: Capture Audio and Video
This example demonstrates the basic use of the getUserMedia method to access both the user's camera and microphone simultaneously. The code requests permission for both video and audio streams using the { video: true, audio: true } constraint, then creates a video element that displays the camera stream in real-time.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Capture Audio and Video</title>
</head>
<body>
<video id="video" autoplay playsinline> </video>
<script>
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
const video = document.createElement('video');
video.autoplay = true;
video.srcObject = stream;
document.body.appendChild(video);
})
.catch(error => {
console.error('Error accessing camera and microphone:', error);
});
</script>
</body>
</html>Key points:
- Uses
{ video: true, audio: true }to request both camera and microphone access; - Creates a video element with autoplay to display the stream from the camera;
- Includes basic error handling with
.catch()for permission denials or device issues.
π Example 2: Stop Device Access
Demonstrates how to properly stop media streams by calling getTracks().forEach(track => track.stop()) on the stream object. This is essential for releasing camera and microphone resources when they're no longer needed.
<script>
stream.getTracks().forEach(track => track.stop());
</script>
Key points:
- Essential for freeing up camera/microphone for other applications;
- Should always be called when device access is no longer needed;
- iOS, Android, and macOS will show a green dot prominently when the camera is accessed.
π€ Example 3: Audio Only Constraint
Shows how to request access to only the microphone using { audio: true } without requesting video.
<script>
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
console.log('Microphone access granted');
})
.catch(error => {
console.error('Error accessing microphone:', error);
});
</script>
Key points:
- Logs success message to console when microphone permission is granted;
- Useful for voice recording or audio chat applications.
πΈ Example 4: Video Only Constraint
Demonstrates requesting access to only the camera using { video: true } without audio.
<script>
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
const video = document.getElementById('video');
video.srcObject = stream;
})
.catch(error => {
console.error('Error accessing camera:', error);
});
</script>
Key points:
- Suitable for applications that need only camera access like taking photos or scanning QR codes.
π Example 5: List Available Devices
Uses navigator.mediaDevices.enumerateDevices() to list all available media input devices (cameras and microphones) on the user's system and get their device ID.
<script>
navigator.mediaDevices.enumerateDevices().then(devices => {
devices.forEach(device => {
console.log(device.kind + ": " + device.label + " id = " + device.deviceId);
});
});
</script>
Key points:
- Logs device kind, label, and deviceId for each camera and microphone;
- Helpful for giving users acess to a custom made device selection UI.
πΈ Example 6: Recording a Video Clip (MediaRecorder)
Shows how to record video and audio using the MediaRecorder interface of the MediaStream Recording API.
<video id="preview" autoplay playsinline width="320" height="240"></video>
<button id="record">Start Recording</button>
<button id="stop" disabled>Stop & Download</button>
<script>
const videoEl = document.getElementById('preview'),
recordBtn = document.getElementById('record'),
stopBtn = document.getElementById('stop');
let recorder, recordedChunks = [];
// 1. Get both video and audio
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
videoEl.srcObject = stream;
// 2. Setup MediaRecorder
recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
if (e.data && e.data.size > 0) {
recordedChunks.push(e.data);
}
};
recorder.onstop = () => {
// Create a Blob from recorded chunks
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
// Create download link
const a = document.createElement('a');
a.style.display = 'block';
a.href = url;
a.download = 'capture.webm';
a.textContent = 'Download recording';
document.body.appendChild(a);
};
})
.catch(console.error);
// 3. Wire up buttons
recordBtn.addEventListener('click', () => {
recordedChunks = [];
recorder.start();
recordBtn.disabled = true;
stopBtn.disabled = false;
});
stopBtn.addEventListener('click', () => {
recorder.stop();
recordBtn.disabled = false;
stopBtn.disabled = true;
});
</script>
Key points:
- Grabs audio + video;
- Pipes it to a <video> for live preview;
- Uses
MediaRecorderto capture chunks; - When stopped, bundles into a
.webmand offers a download link.
πΈ Example 7: Capture Video + Take a Snapshot
Combines live video preview with snapshot functionality using HTML5 canvas.
<video id="cam" autoplay playsinline width="320" height="240"></video>
<button id="snap">Take Snapshot</button>
<canvas id="photo" width="320" height="240"></canvas>
<script>
const video = document.getElementById('cam');
const canvas = document.getElementById('photo');
const snapBtn = document.getElementById('snap');
const ctx = canvas.getContext('2d');
navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" } })
.then(stream => {
video.srcObject = stream;
})
.catch(console.error);
snapBtn.addEventListener('click', () => {
// Draw current video frame onto canvas
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
});
</script>
Highlights:
facingMode: "user"requests the front-facing camera on devices that support it;- Snapshot uses <canvas>βs drawImage() to βfreezeβ the current video frame.
πΈ Example 8: Requesting a Certain Aspect Ratio (Square)
Shows how to request a specific aspect ratio (1:1) from the camera using the aspectRatio constraint and displays the actual achieved dimensions.
<script>
const videoElem = document.getElementById('preview');
const infoElem = document.getElementById('info');
async function startCamera() {
try {
// Desired aspect ratio: 1:1 (square)
const desiredRatio = 1 / 1;
const stream = await navigator.mediaDevices.getUserMedia({
video: {
aspectRatio: { ideal: desiredRatio }
}
});
videoElem.srcObject = stream;
// Inspect actual settings
const track = stream.getVideoTracks()[0];
const settings = track.getSettings();
infoElem.textContent =
`Got ${settings.width}Γ${settings.height} ` +
`(aspectRatio: ${settings.aspectRatio.toFixed(2)})`;
} catch (err) {
console.error('Error opening camera:', err);
infoElem.textContent = 'Unable to access camera with desired aspect ratio.';
}
}
startCamera();
</script>
Key points:
- Specifies desired aspect ratio with
aspectRatio: { ideal: 1/1 }; - Displays actual achieved resolution using
track.getSettings().
π± Example 9: Requesting a Portrait Video Stream With facingMode:user
Demonstrates capturing video in portrait orientation using the front-facing camera by specifying facingMode: "user" and swapped width/height dimensions (720x1280).
<script>
navigator.mediaDevices.getUserMedia({
video: {
width: { ideal: 720 },
height: { ideal: 1280 },
facingMode: "user"
},
audio: false
})
.then(stream => {
const video = document.getElementById('video');
video.srcObject = stream;
})
.catch(error => {
console.error('Error accessing camera:', error);
});
</script>
Key points:
- Swaps dimensions (720Γ1280) to achieve portrait orientation;
- Disables audio with
audio: falsefor video-only capture.
π₯ Example 10: Basic Video Preview (Promise-based)
A simple example showing how to display a live video preview from the camera using promise-based getUserMedia with basic error handling.
<video id="preview" autoplay playsinline width="640" height="480"></video>
<script>
const videoEl = document.getElementById('preview');
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
// Attach the stream to the video element
videoEl.srcObject = stream;
})
.catch(err => {
console.error('Error accessing camera:', err);
});
</script>
What it does:
- Requests camera access;
- If granted, pipes the live video into the <video> element;
- Handles errors (e.g. user denies permission).
π€ Example 11: Async/Await + Audio Only
Shows modern async/await syntax for accessing the microphone, with start/stop buttons to control audio capture
<button id="start">Start Mic</button>
<button id="stop" disabled>Stop Mic</button>
<audio id="player" controls></audio>
<script>
const startBtn = document.getElementById('start');
const stopBtn = document.getElementById('stop');
const player = document.getElementById('player');
let mediaStream;
startBtn.addEventListener('click', async () => {
try {
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
player.srcObject = mediaStream;
startBtn.disabled = true;
stopBtn.disabled = false;
} catch (err) {
console.error('Microphone access error:', err);
}
});
stopBtn.addEventListener('click', () => {
// Stop all audio tracks
mediaStream.getTracks().forEach(track => track.stop());
startBtn.disabled = false;
stopBtn.disabled = true;
});
</script>
Key points:
- Uses
async/awaitfor cleaner control flow; - Demonstrates enabling/disabling controls and stopping tracks.