WebRTC媒體權(quán)限申請getUserMedia實(shí)例詳解
媒體權(quán)限申請
本文主要介紹了 getUserMedia 媒體權(quán)限申請的通用用法,包含權(quán)限申請配置、成功時(shí)媒體流預(yù)覽及銷毀處理、失敗時(shí)的通用提示處理等等
getUserMedia() 方法是用來申請麥克風(fēng)和攝像頭的使用權(quán)限的。該方法存在兼容性問題,需要單獨(dú)處理,如下是比較通用的處理方式:
// 申請媒體權(quán)限的兼容性寫法
function getUserMedia(constrains, success) {
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
const getUserMedia =
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!getUserMedia) {
return Promise.reject(
new Error("瀏覽器不支持訪問用戶媒體設(shè)備,請升級(jí)或更換瀏覽器")
);
}
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
navigator.mediaDevices
// 參數(shù)配置
.getUserMedia(constrains)
// 成功回調(diào) 暴露出去
.then(success)
// 失敗回調(diào) 待通用處理
.catch(mediaErrorCaptured);
}

媒體流預(yù)覽與停止
getUserMedia()方法的返回是一個(gè) promise 對(duì)象,成功后會(huì) resolve 一個(gè) MediaStream 媒體流對(duì)象,包含了請求的媒體類型的軌道,如視頻軌道、音頻軌道。
一般我們會(huì)將返回的 MediaStream 媒體流賦值到 video 元素上,就可以實(shí)現(xiàn)視頻流的預(yù)覽了。
如下所示,同時(shí)申請了攝像頭和麥克風(fēng)權(quán)限,當(dāng)然,可以更改配置,單獨(dú)申請麥克風(fēng)或者攝像頭權(quán)限
getUserMedia(
{
// 需要攝像頭權(quán)限,優(yōu)先使用前置攝像頭 environment-后置攝像頭
video: { facingMode: "user" },
// 需要麥克風(fēng)權(quán)限,false則不需要
audio: true,
},
// 成功的回調(diào)處理
(stream) => {
// 將流數(shù)據(jù)存起來,之后停止流時(shí)需要
localStream = stream;
// 流展示到video標(biāo)簽中
localVideo.current.srcObject = stream;
// 觸發(fā)播放:當(dāng)然這個(gè)也是存在兼容性問題的
// 注意:有時(shí)候因?yàn)闉g覽器的安全限制,是需要與用戶進(jìn)行交互才能自動(dòng)播放的
localVideo.current.play();
}
);
如下為 MediaStream 媒體流對(duì)象的打印展示,以及獲取音頻軌道(getAudioTracks)、獲取視頻軌道 getVideoTracks、獲取所有軌道(getTracks)等方法的打印結(jié)果展示。
注意:MediaStream 的 active 為 true 時(shí),才能正常的預(yù)覽展示;為 false 時(shí)不能正常加載到 video 元素上

一般預(yù)覽成功后,在頁面銷毀之前,需要進(jìn)行關(guān)閉數(shù)據(jù)及清空流的操作
// 方式一:獲取對(duì)應(yīng)的軌道數(shù)據(jù),進(jìn)行清空操作
localStream.getAudioTracks()[0].stop();
localStream.getVideoTracks()[0].stop();
localVideo.current.srcObject = null;
// 方式二:遍歷操作,關(guān)閉媒體軌道
localStream.getTracks().forEach((stream: MediaStreamTrack) => {
stream.stop();
});
媒體申請拒絕處理
如果用戶拒絕了媒體的使用權(quán)限申請,則會(huì) reject 回調(diào)一個(gè)錯(cuò)誤對(duì)象。
因?yàn)殄e(cuò)誤處理是很通用的,所以直接可以通過一個(gè)通用函數(shù)進(jìn)行處理,提高代碼的復(fù)用性。
function mediaErrorCaptured(error) {
console.log("錯(cuò)誤信息name打印", error?.name);
console.log("錯(cuò)誤信息message打印", error?.message);
// 媒體權(quán)限失敗處理(通用 詳細(xì))
const nameMap = {
AbortError: "操作中止",
NotAllowedError: "打開設(shè)備權(quán)限不足,原因是用戶拒絕了媒體訪問請求",
NotFoundError: "找不到滿足條件的設(shè)備",
NotReadableError:
"系統(tǒng)上某個(gè)硬件、瀏覽器或網(wǎng)頁層面發(fā)生的錯(cuò)誤導(dǎo)致設(shè)備無法被訪問",
OverConstrainedError: "指定的要求無法被設(shè)備滿足",
SecurityError: "安全錯(cuò)誤,使用設(shè)備媒體被禁止",
TypeError: "類型錯(cuò)誤",
NotSupportedError: "不支持的操作",
NetworkError: "網(wǎng)絡(luò)錯(cuò)誤發(fā)生",
TimeoutError: "操作超時(shí)",
UnknownError: "因未知的瞬態(tài)的原因使操作失敗)",
ConstraintError: "條件沒滿足而導(dǎo)致事件失敗的異常操作",
};
// 媒體權(quán)限失敗處理(通用 簡單)
const messageMap = {
"permission denied": "麥克風(fēng)、攝像頭權(quán)限未開啟,請檢查后重試",
"requested device not found": "未檢測到攝像頭",
"could not start video source": "無法訪問到攝像頭",
};
let nameErrorMsg = nameMap[error.name];
if (!nameErrorMsg) {
nameErrorMsg = messageMap[error.message.toLowerCase() || "未知錯(cuò)誤"];
}
// todo
alert(nameErrorMsg);
}
當(dāng)然,IOS 和 Android 的權(quán)限拒絕報(bào)錯(cuò)中 message 可能會(huì)不一樣,但是 name 相同,可以結(jié)合二者進(jìn)行判斷
if (
error.message.toLowerCase() === "permission denied" ||
error.name == "NotAllowedError"
) {
console.log(`麥克風(fēng)、攝像頭權(quán)限未開啟,請檢查權(quán)限`);
}
參考文檔:MediaDevices.getUserMedia()
以上就是WebRTC媒體權(quán)限申請getUserMedia實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于WebRTC getUserMedia的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js基于canvas實(shí)現(xiàn)時(shí)鐘組件
這篇文章主要介紹了js基于canvas實(shí)現(xiàn)時(shí)鐘組件的方法,幫助大家更好的理解和使用JavaScript,感興趣的朋友可以了解下2021-02-02
JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary)實(shí)例詳解
這篇文章主要介紹了JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary),結(jié)合實(shí)例形式詳細(xì)分析了javascript數(shù)據(jù)結(jié)構(gòu)中字典的概念、原理、定義與常見使用方法,需要的朋友可以參考下2019-08-08
Webpack學(xué)習(xí)之動(dòng)態(tài)import原理及源碼分析
這篇文章主要為大家介紹了Webpack學(xué)習(xí)之動(dòng)態(tài)import原理及源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
初學(xué)js插入節(jié)點(diǎn)appendChild insertBefore使用方法
由于可見insertBefore()方法的特性是在已有的子節(jié)點(diǎn)前面插入新的節(jié)點(diǎn)但是兩種情況結(jié)合起來發(fā)現(xiàn)insertBefore()方法插入節(jié)點(diǎn),是可以在子節(jié)點(diǎn)列表的任意位置。2011-07-07
js判斷一點(diǎn)是否在一個(gè)三角形內(nèi)
判斷一個(gè)點(diǎn)是否在一個(gè)三角行內(nèi)的代碼2008-02-02

