各位好,在这篇博客中我将向你展示如何在一个网页上通过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
//
// 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
//
// 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)
页面中的演示地址
完整的源代码地址