微信h5页面实现人脸注册和登陆

时间:2024-04-16 13:59:14

工作中总会遇到一些麻烦的问题,有问题不要怕解决就好了,前段时间要实现微信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页面向后端服务做请求,通过用户信息对比是否同一个人,成功并返回登陆信息,进行页面渲染,进入到功能页面。

这样就实现了在微信的整个人脸注册/登陆的流程,比较绕,也比较笨,没有找到更好的办法只能先这么做,等想到更好的办法的时候再替换,若有小伙伴也是同样的需求,并且有更好的解决方法,请留言,或发邮箱544785380@qq.com,感激不尽,写的不好,也有瑕疵,仅作为一次经验参考,有不对的地方希望小伙伴们能批评指出,我及时改正。

 

每一个努力的人都值得被肯定,但是最大的肯定来源于自己!!!

     加油每一天!!!

 

附加:不知道js怎么录制视频的小伙伴可以参考:https://blog.****.net/mrzhangdulin/article/details/84560146