各位好,在這篇博客中我將向你展示如何在一個網頁上通過JavaScript, 且支持衆多瀏覽器不需要額外的庫訪問當前的設備相機。
如何訪問相機
我們使用JavaScript 的 Media Stream API去訪問用戶的相機(不止是在電腦上,手機上也是如此),這個API允許通過流去訪問設備捕獲的視頻和音頻。
第一步是檢測當前瀏覽器是否支持該API:
if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
// 表明當前瀏覽器支持該API
}
事實上,現代瀏覽器對該API的支持相當不錯(當然,是不包括Internet Explorer)
捕獲視頻流
爲了捕獲設備生成的視頻流,我們使用mediaDevices
對象上的getUserMedia
方法。
此方法接收一個對象,該對象包含我們所請求的媒體類型(視頻或音頻)和一些需求條件,首先,我們可以傳遞參數{video: true}
從攝像機獲取視頻。
const videoStream = await navigator.mediaDevices.getUserMedia({ video: true })
執行這條語句將會要求用戶授權程序訪問相機的權限,如果用戶拒絕,這將會拋出一個異常並且不會有期望的視頻流返回。因此我們必須在try/catch
語法塊中處理這種情況。
注:該方法將會返回一個Promise,因此你可以必須使用async/await
或者then
語法。
獲取視頻流的其他參數
我們可以通過傳遞所需的分辨率和最小和最大限制的信息來提高視頻的要求:
const constraints = {
video: {
width: {
min: 1280,
ideal: 1920,
max: 2560,
},
height: {
min: 720,
ideal: 1080,
max: 1440,
},
},
}
const videoStream = await navigator.mediaDevices.getUserMedia(constraints)
這樣,該視頻流以正確的寬度和高度比例進入。 如果它是處於縱向模式的手機,則需要進行尺寸反轉。
在頁面上顯示視頻
好了,現在我們有了視頻流,我們能做些什麼呢?
我們可以通過video
元素,將視頻顯示到頁面上。
// considering there is a
// <video autoplay id="video"></video>
// tag in the page
const video = document.querySelector('#video')
const videoStream = await navigator.mediaDevices.getUserMedia(constraints)
video.srcObject = videoStream
注:在video
元素中有autoplay
屬性,如果沒有,你需要顯式地調用video.play()
方法來顯示圖像
訪問手機上的前後相機
getUserMedia
方法默認會使用操作系統默認的視頻錄製設備,在有兩個攝像頭的手機中,它使用的是前置攝像頭。
爲了訪問後置相機,我們需要在傳遞視頻參數時包含facingMode: "environment"
:
const constraints = {
video: {
width: { ... },
height: { ... },
facingMode: 'environment'
}
}
默認facingMode
字段的值是'user'
,它表明是前置相機
請注意,如果您想在播放視頻時更換相機,你需要停止當前流,然後用其他相機的流替換它。
videoStream.getTracks().forEach(track => {
track.stop()
})
製作截圖
另外很酷的一點是,你可以捕獲視頻的截圖。
你可以將當前的視頻幀圖像繪製到canvas
元素上,如下:
// considering there is a
// <canvas id="canvas"></canvas>
// tag in the page
const canvas = document.querySelector('#canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
canvas.getContext('2d').drawImage(video, 0, 0)
你也可以將顯示到canvas
元素上的內容放到一個img
元素上。
在本教程創建的示例中,我添加了一個按鈕,該按鈕可從畫布動態創建圖像並將其添加到頁面。 代碼如下:
const img = document.createElement('img')
img.src = canvas.toDataURL('image/png')
screenshotContainer.prepend(img)
結論
頁面中的演示地址
完整的源代碼地址