When using WebRTC, you must first obtain camera/microphone permissions using getUserMedia to invoke the mediaDevices related interface
Version 1: Obtain permissions directly
/ / release mediaStream
const stopStreamTracks = stream= > {
if(! stream || ! stream.getTracks) {return;
}
try {
const tracks = stream.getTracks();
tracks.forEach(it= > {
try {
it.stop();
} catch (errMsg) {
// debugger;}}); }catch (errMsg) {
// debugger;}};Copy the code
// Request camera/microphone permissions
const requestPermission = async() = > {try {
const stream = await global.navigator.mediaDevices.getUserMedia({ video: true.audio: true });
stopStreamTracks(stream);
if (stream) {
return true; }}catch (errMsg) {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false; }}return true;
};
Copy the code
GetUserMedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected.getUsermedia rejected
Version 2: Filters the device list and dynamically requests device permissions
// Get the device list
const enumerateDevices = async() = > {try {
const devices = await global.navigator.mediaDevices.enumerateDevices();
return devices;
} catch (errMsg) {
return[]; }};// Request camera/microphone permissions
const requestPermission = async() = > {const devices = await enumerateDevices();
const constraints = devices.reduce(
(info, device) = > {
if(! device) {return info;
}
if ('videoinput' === device.kind) {
return { video: true.audio: info.audio };
}
if ('audioinput' === device.kind) {
return { audio: true.video: info.video };
}
return info;
},
{ video: false.audio: false});try {
const stream = await global.navigator.mediaDevices.getUserMedia(constraints);
stopStreamTracks(stream);
} catch (errMsg) {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false; }}return true;
};
Copy the code
This version also worked well for a while, until we encountered customers using PCIE collection cards under Linux, because enumerateDevices was called before getUserMedia, using 4-way PCIE collection cards in Chrome under Linux, The device deviceId returned from the device list was empty and had only one device, which was not expected. Version 3 was developed based on this problem.
Version 3: Roll back gradually and check multiple times
- Step 1: Try to obtain both camera and microphone permissions. If NotAllowedError is abnormal, the user refuses to provide permissions. Otherwise, go to the next step
- Step 2: Obtain the microphone permission separately (the microphone is more important than the camera). If the exception occurs, go to the next step
- Step 3: Obtain the camera permission separately and check the exception cause
- Step 4: If none of the three exceptions is caused by NotAllowedError, then consider it a device exception and do not prompt the user for insufficient permissions
// Request camera/microphone permissions
const requestPermission = async() = > {// Step 1: Try to get both camera and microphone permissions
try {
const stream = await global.navigator.mediaDevices.getUserMedia({ video: true.audio: true });
stopStreamTracks(stream);
if (stream) {
return true; }}catch (errMsg) {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false; }}try {
const stream = await global.navigator.mediaDevices.getUserMedia({ video: false.audio: true });
stopStreamTracks(stream);
if (stream) {
return true; }}catch (errMsg) {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false; }}try {
const stream = await global.navigator.mediaDevices.getUserMedia({ video: true.audio: false });
stopStreamTracks(stream);
if (stream) {
return true; }}catch (errMsg) {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false; }}return true;
};
Copy the code
No problems have been found in version 3. Follow-up updates will continue if problems occur.
Slightly optimized the code
function getDevicePermission(constraints) {
return global.navigator.mediaDevices
.getUserMedia(constraints)
.then(stream= > {
if (stream) {
stopStreamTracks(stream);
return true;
}
return Promise.reject(new Error('EmptyStreamError'));
})
.catch(errMsg= > {
if (errMsg && 'NotAllowedError' === errMsg.name) {
return false;
}
return Promise.reject(errMsg);
});
}
function requestPermission() {
return getDevicePermission({ video: true.audio: true })
.catch(() = > getDevicePermission({ video: false.audio: true }))
.catch(() = > getDevicePermission({ video: true.audio: false }))
.catch(() = > true);
}
Copy the code