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
。
瀏覽器兼容性
語法
navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) { ... })
.catch(function(error) { ... })
參數
containers:
指定請求的媒體類型,主要包含video
和audio
,必須至少一個類型或者兩個同時可以被指定。如果瀏覽器無法找到指定的媒體類型或者無法滿足相對應的參數要求,那么返回的Promise
對象就會處於rejected
[失敗]狀態,NotFoundError
作為rejected
[失敗]回調的參數。
【例】同時請求不帶任何參數的音頻和視頻:
{ audio: true, video: true }
【例】使用1280x720的攝像頭分辨率:
{
audio: true,
video: { width: 1280, height: 720 }
}
【例】要求獲取最低為1280x720的分辨率:
{
audio: true,
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 776, ideal: 720, max: 1080 }
}
}
當請求包含一個ideal
(應用最理想的)值時,這個值有着更高的權重,意味着瀏覽器會先嘗試找到最接近指定的理想值的設定或者攝像頭(如果設備擁有不止一個攝像頭)。
【例】優先使用前置攝像頭(如果有的話):
{ audio: true, video: { facingMode: "user" } }
【例】強制使用后置攝像頭:
{ audio: true, video: { facingMode: { exact: "environment" } } }
成功回調函數seccessCallback
的參數stream
:stream
是MediaStream
的對象,表示媒體內容的數據流,可以通過URL.createObjectURL
轉換后設置為Video
或Audio
元素的src
屬性來使用,部分較新的瀏覽器也可以直接設置為srcObject
屬性來使用。
注意:新版的谷歌瀏覽器不能直接將MediaStream對象直接作為URL.createObjectURL的參數使用,會報TypeError Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided的錯誤,具體用法在后面說明。
失敗回調函數errorCallback
的參數error
,可能的異常有:
AbortError
:硬件問題NotAllowedError
:用戶拒絕了當前的瀏覽器實例的訪問請求;或者用戶拒絕了當前會話的訪問;或者用戶在全局范圍內拒絕了所有媒體訪問請求。NotFoundError
:找不到滿足請求參數的媒體類型。NotReadableError
:操作系統上某個硬件、瀏覽器或者網頁層面發生的錯誤導致設備無法被訪問。OverConstrainedError
:指定的要求無法被設備滿足。SecurityError
:安全錯誤,在getUserMedia()
被調用的Document
上面,使用設備媒體被禁止。這個機制是否開啟或者關閉取決於單個用戶的偏好設置。TypeError
:類型錯誤,constraints
對象未設置[空],或者都被設置為false
。
示例:HTML 5調用媒體設備攝像頭
這個例子中,請求訪問用戶硬件設備的攝像頭,並把視頻流通過Video元素顯示出來。網頁中提供一個"拍照"的按鈕,通過Canvas將Video的畫面截取並繪制,核心代碼如下:
HTML
<!--video用於顯示媒體設備的視頻流,自動播放--> <video id="video" autoplay style="width: 480px;height: 320px"></video> <!--拍照按鈕--> <div> <button id="capture">拍照</button> </div> <!--描繪video截圖--> <canvas id="canvas" width="480" height="320"></canvas>
JavaScript
//訪問用戶媒體設備的兼容方法 function getUserMedia(constrains,success,error){ if(navigator.mediaDevices.getUserMedia){ //最新標准API navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error); } else if (navigator.webkitGetUserMedia){ //webkit內核瀏覽器 navigator.webkitGetUserMedia(constrains).then(success).catch(error); } else if (navigator.mozGetUserMedia){ //Firefox瀏覽器 navagator.mozGetUserMedia(constrains).then(success).catch(error); } else if (navigator.getUserMedia){ //舊版API navigator.getUserMedia(constrains).then(success).catch(error); } } var video = document.getElementById("video"); var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); //成功的回調函數 function success(stream){ //兼容webkit內核瀏覽器 var CompatibleURL = window.URL || window.webkitURL; //將視頻流設置為video元素的源 video.src = CompatibleURL.createObjectURL(stream); // 此處的代碼將會報錯 解決的辦法是將video的srcObject屬性指向stream即可 //播放視頻 video.play(); } //異常的回調函數 function error(error){ console.log("訪問用戶媒體設備失敗:",error.name,error.message); } if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia){ //調用用戶媒體設備,訪問攝像頭 getUserMedia({ video:{width:480,height:320} },success,error); } else { alert("你的瀏覽器不支持訪問用戶媒體設備"); } //注冊拍照按鈕的單擊事件 document.getElementById("capture").addEventListener("click",function(){ //繪制畫面 context.drawImage(video,0,0,480,320); });
關閉攝像頭或者麥克風:需要注意的是,MediaStream.getTracks() 返回的Tracks數組是按第一個參數倒序排列的
比如現在定義了
{ video: true, audio: true }
想關閉攝像頭,就需要調用MediaStream.getTracks()[1].stop();
同理,0對應於audio的track
進階
對本示例進行功能加強,比如使用CSS 3 的濾鏡實現模糊、黑白等效果。
麥克風
因為純粹用一個audio標簽來播放麥克風拾取到的聲音顯得太沒特色了,於是我用到了以前寫的一個音頻可視化庫Vudio.js,代碼如下:
創建一個canvas來顯示音頻波形圖
<canvas id="canvas"></canvas>
通過Vudio.js和getUserMedia來顯示麥克風拾取到的音頻的波形
var canvas = document.querySelector('#canvas') navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => { // 調用Vudio var vudio = new Vudio(stream, canvas, { accuracy: 256, width: 1024, height: 200, waveform: { fadeSide: false, maxHeight: 200, verticalAlign: 'middle', horizontalAlign: 'center', color: '#2980b9' } }) vudio.dance() }).catch((error) => { console.error(error.name || error) })
vudio.js源碼:https://github.com/margox/vudio.js/blob/master/vudio.js
效果如下圖所示: