How to build beautiful camera/microphone permission checking for websites
A great UX for camera and microphone permissions is critical for all video chatting sites, but can feel impossible to get right: every browser and OS throws different errors and none have it documented. Our team is open-sourcing our repo (mic-check) to improve video chat experiences around the web.
There’s lot of cases to handle, all of which vary across browsers and operating systems. They stem from a few issues:
- People click “Block” when the permission is requested
- Browser is missing permission to access camera, needs settings changed in system preferences
- Another site or app is using camera
- So many more issues
Identifying such errors and explaining to users how to correct them should be easy, but it isn’t. This resulted in endless support tickets and as a small startup, eats up all of our time!
We’ve frequently encountered these problems and worked hard to design a better onboarding experience for video and audio. To help other developers, we are open sourcing our lightweight npm package called mic-check for requesting camera and microphone permissions with better error handling.
The Problem
In an ideal world, there would be a single API with consistent performance across all browsers and operating systems to request camera and microphone permissions cleanly. The Permissions API works towards building that but is currently unsupported on Safari. So for now, the best solution is to use navigator.mediaDevices.getUserMedia().
When this function is first called, users receive a popup from the browser requesting camera and microphone access. If successful, you get the media streams which is relatively straightforward. But the errors are completely inconsistent across platforms. Firefox is the only browser with any error documentation for this method at all.
Browser Differences
Across all of the major browsers (Chrome, Safari, Edge, Firefox), the getUserMedia() method returns drastically different errors. Chrome and Edge will have errors named “NotAllowedError” or “NotReadableError” with drastically different error messages. Firefox, on the other hand, also has “NotFoundError” and “AbortError”.
These are also the overarching names of errors with the details often coming in the message, like “Permission denied by system.” How a user should respond to an error is dependent on both the error name and the error message.
OS Differences
On macOS, you’ll frequently have cases where a browser like Chrome is unable to access the camera giving a “NotAllowedError: Permission denied by system”. You might have to prompt the user to open System Preferences and grant access to the browser.
On Windows, other apps and browser tabs can have control of the camera and prevent your website from accessing the video stream. You’ll have to tell the user to close all other apps using the camera.
With multiple browsers and OS’s each with its own set of errors and poor documentation, deciding what to present to the user can quickly become a nightmare.
The Errors
Since getUserMedia() has poor error documentation, our team took the time to put together a list of common errors. We’ve broadly categorized them as SystemPermissionDenied, UserPermissionDenied, and CouldNotStartVideoSource.
Can I get a mic-check?
In order to help developers request camera and microphone permissions without having to handle every individual error per platform, we built mic-check! The package contains only one dependency for browser detection (bowser) and helps you understand errors without having to deal with the specifics.
mic-check is available as an npm package and can be easily installed with npm i mic-check
or yarn add mic-check
.
Its usage is as shown below:
UI for Permissions
Understanding the error is just part of the problem. You also need to present action items to the user to help them resolve any issues. We’ve generally found Google Meet to have one of the best experiences for onboarding and have designed a similar UI.
An example of how to build these screens in a React App can be found here.
Initial Permissions Request
When initially requesting permissions, you should let the user know why you are asking.
SystemPermissionDenied
If the browser doesn’t have access to the camera and microphone, you should explain to the user and deep-link to the appropriate Settings app when possible.
UserPermissionDenied
If the user initially denied permissions, you should indicate where on the browser they can go to change the settings to “Allow”.
CouldNotStartVideoSource
This problem is most common on Windows and happens when another application (Zoom, Webex) or browser tab (Google Meet, Messenger Video) is already using the video stream. You should recommend that users close out other video apps.
We hope this helps other developers looking to build the next round of innovations in video!