摘要:HTML5的getUserMedia API為用戶提供訪問硬件設備媒體(攝像頭、視頻、音頻、地理位置等)的接口,基于該接口,開發者可以在不依賴任何瀏覽...
HTML5的getUserMedia API為用戶提供訪問硬件設備媒體(攝像頭、視頻、音頻、地理位置等)的接口,基于該接口,開發者可以在不依賴任何瀏覽器插件的條件下訪問硬件媒體設備。
getUserMedia API最初是navigator.getUserMedia,目前已被最新Web標準廢除,變更為navigator.mediaDevices.getUserMedia(),但瀏覽器支持情況不如舊版API普及。
MediaDevices.getUserMedia()方法提示用戶允許使用一個視頻和/或一個音頻輸入設備,例如相機或屏幕共享和/或麥克風。如果用戶給予許可,就返回一個Promise對象,MediaStream對象作為此Promise對象的Resolved[成功]狀態的回調函數參數,相應的,如果用戶拒絕了許可,或者沒有媒體可用的情況下PermissionDeniedError或者NotFoundError作為此Promise的Rejected[失敗]狀態的回調函數參數。注意,由于用戶不會被要求必須作出允許或者拒絕的選擇,所以返回的Promise對象可能既不會觸發resolve也不會觸發 reject。
在你的getUserMedia()開始運行的那一瞬間,就會可能會遇到各種各樣的錯誤:
1. 用戶沒有攝像頭,只有一個麥克風
2. 用戶(不小心地)拒絕了瀏覽器的使用攝像頭請求
3. 用戶在你的getUserMedia()代碼已經初始化之后才將攝像頭/麥克風插到電腦上
4. 媒體設備已經被其他的應用所占用了
5. 只針對Firefox:設備已經被Firefox瀏覽器的其他標簽頁所占用了
為了解決這些狀況,在管理getUserMedia()的媒體捕捉和流規范中定義了幾種你可以在代碼中處理的錯誤。
下圖列出了幾種最常見的錯誤。在Firefox和Chrome中錯誤的名稱有所不同。規范中還有對AboutError和SecurityError的定義,但是永遠觸發不了它們。
NotFoundError
這個問題真的是非常常見,當你通過約束請求一個視頻軌道但是用戶沒有攝像頭的時候,這個錯誤就會出現。還有,當你請求一個音頻/麥克風軌道的時候,但是電腦/設備并沒有聲卡或者錄音設備被系統禁用的時候也會出現這個錯誤。但是這種情況比較罕見。
Firefox會彈出一個MediaStreamError,其名稱屬性為“NotFoundError”并顯示消息“無法找到該對象”。
Chrome會出現一個NavigatorUserMediaError,其名稱屬性為“DevicesNotFoundError”。
NotReadableError
這種情況會在Windows系統上發生,當瀏覽器想要使用網絡攝像頭或者麥克風的時候卻發現他們已經被使用了(比如說Skype正在用)。在Windows上這個錯誤很常見,因為進程可以獨占攝像頭的訪問權。除了Firefox,它不會在macOS上出現因為mac系統允許幾個進程共享攝像頭/麥克風的使用權限。
在Windows系統上,Firefox會在其他應用或者Firefox標簽頁正在使用攝像頭或者麥克風的時候彈出這個錯誤。這個錯誤類型是MediaStreamError,名稱屬性被設置為“NotReadableError”,消息屬性被設置為“未能分配視頻源”。
Windows系統上的Chrome瀏覽器會彈出一個NavigarUserMediaError,其名稱屬性被設為“TrackStartError”,非規范的Chrome特定版本,沒有消息提示。不同的Chrome標簽頁可以共享同一個攝像頭。
在mac系統上,這個錯誤只有在Firefox不止一個標簽頁嘗試獲取攝像頭和麥克風的時候出現。會提示一個消息“當前麥克風進程受限”。
OverconstrainedError
當你請求一個無法用硬件滿足的約束時會出現在這個錯誤,舉個例子,當使用min或者exact關鍵詞請求一個比較高的幀速率或者高的分辨率的時候就會出現此錯誤。
Firefox會提出一個MediaStreamError,其名稱屬性被設為“OverconstrainedError”。
Chrome會彈出一個NavigatorUserMediaError,其名稱屬性設為“ConstraintNotSatisfiedErrror”,一個非規范的Chrome特定版本。
Chrome和Firefox會返回請求的分辨率,或者當使用了ideal值的時候返回一個最接近的分辨率,但是如果你開始使用的是min關鍵字并賦予了比較大的值,或者exact關鍵字含有不支持的值,你就會立即觸發這個錯誤。
錯誤項還會通過constraintName屬性提醒你約束無法滿足,并且會彈出消息“約束無法滿足”。
NotAllowedError
當用戶拒絕(或者之前拒絕過)攝像頭或者麥克風的使用請求時就會出現這個錯誤。
Firefox會出現MediaStreamError,名稱屬性設置為“NotAllowedError”,以及彈出消息“用戶代理或者當前平臺不允許該請求”。
Chrome會出現NavigatorUserMediaError,其名稱屬性設為“PermissionDeniedError”。
TypeError
當傳遞給getUserMedia()的約束對象為空或者將所有軌道(音軌,視頻軌,或者兩者)被設置為false的時候就會出現這個問題。
Firefox會提出MediaStreamError,其名稱屬性設置為“TypeError”,以及一個消息“音頻和/或視頻被請求”。
Chrome會出現一條“TypeError:無法在‘MediaDevices’上執行‘getUserMedia’:必須至少請求一個音頻和視頻”。
解決這些錯誤,使用基于新的promise的getUserMedia()處理這些錯誤就很簡單了,以使用下面的代碼:
// 兼容性檢測 function is_supported_get_userMedia() { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; constraints = { audio: false, video: {width: { ideal: 470 },height: { ideal: 470 }} }; if (navigator.getUserMedia) { navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) { var mediaStreamTrack; mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0]; mediaStreamTrack && mediaStreamTrack.stop(); }).catch(function (err) { if (err.name == 'NotFoundError' || err.name == 'DevicesNotFoundError'){ is_supported_userMedia = USERMEDIA_MAP.without_camera; } else if(err.name == 'NotReadableError' || err.name == 'TrackStartError'){ is_supported_userMedia = USERMEDIA_MAP.already_used; } else if(err.name == 'OverconstrainedError' || err.name == 'ConstraintNotSatisfiedErrror'){ is_supported_userMedia = USERMEDIA_MAP.error_constraint; } else if(err.name == 'NotAllowedError' || err.name == 'PermissionDeniedError'){ is_supported_userMedia = USERMEDIA_MAP.not_forbidden; } else if(err.name == 'TypeError' || err.name == 'TypeError'){ is_supported_userMedia = USERMEDIA_MAP.empty_constraint; } isPlay = false; }); } else { is_supported_userMedia = USERMEDIA_MAP.not_suppeort; isPlay = false; } }; function check_network_protocol_support() { is_supported_get_userMedia(); if (is_supported_userMedia == USERMEDIA_MAP.not_suppeort) { video.pause(); layer.alert('請使用谷歌(Chrome)或火狐(Firefox)瀏覽器', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.without_camera) { video.pause(); layer.alert('當前設備未安裝網絡攝像頭', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.already_used) { video.pause(); layer.alert('攝像頭或者麥克風已經被占用', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.error_constraint) { video.pause(); layer.alert('太高的幀速率或者高的分辨率', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.not_forbidden) { video.pause(); layer.alert('用戶拒絕(或者之前拒絕過)攝像頭或者麥克風的使用權限', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.empty_constraint) { video.pause(); layer.alert('當傳遞給getUserMedia()的約束對象為空或者將所有軌道', { icon: 5 }); return false; } else if (is_supported_userMedia == USERMEDIA_MAP.unknown) { video.pause(); layer.alert('未知錯誤', { icon: 5 }); return false; } return true; };
網友評論:
網友 : 大神,官網怎么打不開了呢,還在繼續開發嗎,特別喜歡這個系統,簡潔流暢,希望繼續加油啊。 管理員:放心吧,yzmcms系統一直在更新
2020-12-30 22:50:33 回復
網友評論:
大神,官網怎么打不開了呢,還在繼續開發嗎,特別喜歡這個系統,簡潔流暢,希望繼續加油啊。
2020-12-28 11:56:00 回復