工作中总会遇到一些麻烦的问题,有问题不要怕解决就好了,前段时间要实现微信h5页面人脸注册/登录,本以为很简单的一个东西,没想到居然这么麻烦,写个文章记录下过程和遇到的问题及解决办法:
需求:①人脸注册,需进行活体认证,用户利用摄像头拍摄一段视频并朗读生成的4位随机数。
②人脸登陆:静默登陆,打开摄像头拍照并上传,与底板进行对比。
① 最开始是想利用下面的打开摄像头
navigator.mediaDevices.getUserMedia
然后利用下面的去捕获媒体流
var mediaRecorder = new MediaRecorder(stream,{ mimeType:'video/webm;codecs=h264' });
再把捕获的媒体流通过表单进行上传
var file = new File([recorderFile], 'msr-' + (new Date).toISOString().replace(/:|\./g, '-') + '.mp4', { type: 'video/mp4' }); var data = new FormData(); data.append("username", "test"); data.append("file", file);
最后发现上传和下载下来的视频都没有画面,不管怎么调编码,就是这个mimeType:'video/webm;codecs=h264',都是只有声音没有画面,没办法就换了另外一个想法,牛掰的input,利用input去调用本地摄像机,录制完成后通过onchange事件实现自动上传视频,这样就解决了没有画面的问题,而且苹果和安卓都是兼容的,代码如下:
HTML
<form id="modify2" name="getForm" enctype="multipart/form-data" method="post"> <input type="file" name="video" accept="video/*" capture="user" class="openCamera" onchange="openCamera()"/> </form>
JS
function openCamera(){ const formDate = new FormData($("#modify")[0]) formDate.append("username",username) $.ajax({ type:"post", url:"urlXXX", data:formDate, mimeType:"multipart/form-data", contentType:false, cache:false, processData:false, success:function(data){ console.log(data) }, error:function(res){ console.log(res) } }); }
这样就实现了活体验证,进行了人脸注册。
②在做这个时候也是用了getUserMedia这个方法,然后在用canvas进行截图,最后上传,代码如下:
HTML
<div class="videoJt"> <video width='115' height='150' autoplay muted id="video" webkit-playsinline='true' playsinline='true'></video> <canvas id="canva" width='150' height='150'></canvas> </div>
JS
function start(){ function $$(elem) { return document.querySelector(elem); } var canvas = $$('#canva'), context = canvas.getContext('2d'), video = $$('#video') //打开摄像头 navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || window.getUserMedia; var constraints = {video: true, audio: false}; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { video.srcObject = stream // video.play() setTimeout(function(){ screenshot() },6000) }).catch(function(err) { console.log(err); }) }else if (navigator.getUserMedia) { navigator.getUserMedia(constraints, function (stream) { video.srcObject = stream; setTimeout(function(){ screenshot() },6000) }, function (err) { callback(err); }); } else { console.log(new Error('Not support userMedia')); } // 截取图像 function screenshot(){ context.drawImage(video, 0, 0, 115, 150); let base64Data = canvas.toDataURL('image/png'); let blob = dataURItoBlob(base64Data); let fd = new FormData(); fd.append('image_best',blob); fd.append('username',username); closeMedia(); upload(fd); } // 关闭摄像头 function closeMedia(videoElem){ let stream = video.srcObject; let tracks = stream.getTracks(); tracks.forEach(function(track){ track.stop(); }) video.srcObject = null; } //base64转图片 function dataURItoBlob (base64Data) { var byteString; if (base64Data.split(',')[0].indexOf('base64') >= 0) byteString = atob(base64Data.split(',')[1]); else byteString = unescape(base64Data.split(',')[1]); var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0]; var ia = new Uint8Array(byteString.length); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ia], {type: mimeString}); }; // 上传截取的图像 function upload(data1) { $.ajax({ type:"post", url:"urlXXX", data:data1, dataType:"JSON", mimeType:"multipart/form-data", contentType:false, cache:false, processData:false, success:function(json){ console.log(json); }, error:function(res){ console.log(res); } }); } }()
本以为这样就OK了,本人是安卓机测试是好的,就兴冲冲的在苹果上测,居然没有反应,原来是ios的微信中是没有getUserMedia的,没办法想出在进入这里的时候判断是不是ios的微信,是那就提示利用外部浏览器打开,这样也很麻烦,对苹果用户不是很友好,每次用人脸登陆都要跳出去很麻烦,因为是公众号的H5,所以想到利用微信的jssdk,按照微信公众平台的方法,引用了jssdk,看了api,有一个是创建相机wx.createCameraContext,但是在打印的时候报错,createCameraContext not a function,一看是没有,就选择了chooseImage,提示没有权限,又配置了wx.config才好用,调用起来之后和需求不太一样,不是静默的,于是就想到了一个迂回的办法:
利用小程序,如图:
通过公众号点击打开小程序,这时小程序去请求后台服务,判断是否需要人脸登陆,不需要直接把返回的url直接填入web-view打开h5页面即可,需要就通过小程序调用wx.createCameraContext进行静默拍照并上传,后端服务记录一次当前是登陆人的信息,成功后用web-view打开h5页面,在h5页面向后端服务做请求,通过用户信息对比是否同一个人,成功并返回登陆信息,进行页面渲染,进入到功能页面。
这样就实现了在微信的整个人脸注册/登陆的流程,比较绕,也比较笨,没有找到更好的办法只能先这么做,等想到更好的办法的时候再替换,若有小伙伴也是同样的需求,并且有更好的解决方法,请留言,或发邮箱[email protected],感激不尽,写的不好,也有瑕疵,仅作为一次经验参考,有不对的地方希望小伙伴们能批评指出,我及时改正。
每一个努力的人都值得被肯定,但是最大的肯定来源于自己!!!
加油每一天!!!
附加:不知道js怎么录制视频的小伙伴可以参考:https://blog.csdn.net/mrzhangdulin/article/details/84560146