-
需求:在手机端(主要是微信浏览器)打开网页进行人脸识别,及身份证图片识别
-
分析:需要在页面中实时显示当前视频,并进行自动人脸采集和比对
- 方案一:使用input标签,进行用户手动拍照和录像。然后调用后台识别接口进行人脸识别(ios android 的微信、浏览器均支持,不过不能自定义样式,只能使用手机原生的拍照页面,不能做遮罩层)
- 方案二(该方案仅仅支持android的微信、浏览器、ios的safary浏览器):
- 使用新接口getUserMedia接口(详情请查看mdn)将实时采集到的前置或者后置摄像头实时显示到页面的video元素上,然后再表面做遮罩层。
- 使用 tracking.js进行实时的视频或者图像进行人脸检测,只有检测通过才调用后台接口。
- 身份证拍摄页面要调取后置摄像头,在表面做一个长方形的框框,方便用户拍摄,用户点击拍摄后,获取当前的video 帧 drawImage到一个canvas上面,然后从canvas获取base64的图片数据发送到后端实现人脸识别。
-
最终解决方法: 判断当前手机,如果为安卓,则使用getUserMedia方案,如果调取getUserMedia报错,则调整为ios的input方案。
-
注意点汇总:
- getUserMediaJ接口中的参数支持问题
this.getUserMedia({ audio: true, video: { facingMode: { exact: 'environment' } } }, this.getIdVideoSuccess, this.getIdVideoError)- 不支持 exact 参数,要写成如下:
this.getUserMedia({ audio: true, video: { facingMode: 'environment'} }, this.getIdVideoSuccess, this.getIdVideoError) // 如果这种情况下输入width 合 height 会报 - srouce不可用问题。也就是说在使用后置摄像头的情况,下,如果输入了width和height,手机没有对应分辨率的宽高视频流,就会报错。- getUserMedia 输入参数中 width & height 是反的:
this.getUserMedia({ audio: false, video: { facingMode: 'user', width: this.clientH, height: this.clientW } }, this.getFaceVideoSuccess, this.getFaceVideoError)- 其中有两个功能,一个是调取前景摄像头进行人脸采集,然后如果人脸识别没有通过,再进行调取后置摄像头拍摄照片进行身份证照片拍摄。遇到问题:当调用完前置或者后置摄像头后,第二次调用前置或者后置摄像头会获取不到流,报错。原来是因为,第一次使用流后没有关闭,代码如下:
// 其中this.faceVideo是video元素队形 // this.faceStream是调用getUserMedia成功后返回的stream closeFaceVideo() { if (this.faceVideo) { if (this.faceStream) { try { let tracks = this.faceStream.getTracks() if (tracks) { tracks.forEach(item => { console.log('the face stream tracks') this.log('the face stream tracks') console.log(item) item.stop() }) } } catch(e) { console.log(e) } } this.faceVideo.pause() this.faceVideo.srcObject = null } },作者说:之前拿到这个需求的时候,进行了多方面的调研,想找到一个适配各种手机和浏览器类型的方案。当时也在一些前端技术群中求教了各位前端大佬,也得到了很多很有启发的反馈,心存感激,因此写下这篇文章,给后续需要的同行。如果大家有更好的解决方案,或者文章有什么不对的,也请指出。互相学习,共同进步。