mediaDevices对象和网页调起摄像头拍照

444 阅读2分钟

最近接到一个少见的需求:在PC端网页调起摄像头并拍照,做完后顺势研究了下mediaDevices这个对象:
(以下内容皆在chrome浏览器中测试)

1.window.navigator.mediaDevices

window对象提供的媒体设备管理对象,供用户调起摄像头,麦克风等设备,还可以实现屏幕共享等功能。在控制台中输入后,打印出的内容为:

微信截图_20230216220104.png

2.mediaDevices.enumerateDevices

一个返回Promise对象的函数,fulfilled后返回一个数组,数组内容为当前机器可用的设备数组。
数组子项结构为:
deviceId:设备ID
groupId:设备组ID,同类型的输入设备会被赋予相同的设备组ID,如多个麦克风
kind:设备类型,如videoinput代表摄像头
label:设备名称
这里有一个要提醒的点是:如果某个类型的设备没有得到用户授权的话,其对象依旧会在数组中被返回,但其deviceId和label会为空,所以最好确保得到用户授权后再调用enumerateDevices以获取完整的设备信息。

3.mediaDevices.getUserMedia

一个返回Promise对象的函数,接受一个参数作为配置项,fulfilled后返回一个媒体流mediaStream。
举个例子:

navigator.mediaDevices.getUserMedia({
    audio: true,
    video:{
        width:720,
        height:405,
        deviceId:'abc'
    }
}).then((stream)=>{});

使用这些参数,我们会获得设备ID为abc的摄像头拍摄的宽720高405且带有音频的媒体流,如果获取途中发生错误(如声明了audio但无收音设备),可以用catch获取具体错误对象。
可以指定使用的设备ID在机器拥有多个同类型输入设备时非常有用,通过enumerateDevices获取设备列表和设备ID后,可以使用select标签渲染到页面上供用户切换使用。

4.授权

当我们调用mediaDevices.getUserMedia时,浏览器会先获取当前网站的授权情况,如果没有历史授权且当前配置为“询问”时,浏览器就会弹窗询问用户“是否允许当前页面打开摄像头”,允许后才能获取媒体流。浏览器会记住用户当前选择,下次调用getUserMedia时将遵循历史授权情况执行。
跟很多其他配置一样,这个授权一旦被拒绝,用户必须在浏览器配置中手动打开才能才重新调用getUserMedia。

微信截图_20230216225004.png

5.媒体流mediaStream

成功调用getUserMedia后返回的媒体流,可以通过URL.createObjectURL转换成video或audio标签可使用的src属性,部分浏览器可以直接设置为srcObject属性来使用。

6.拍照

video的dom对象能直接被canvas截取,使用drawImage截取当前帧:

const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.drawImage(video,0,0,720,405);
let result = canvas.toDataURL('image/png');

通过toDataURL把截取帧转化为base64图片后就可以放到img标签中展示或者供用户下载了。