import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.bfdb.entity.H5faceliving.H5FacelivingRoot;
import com.bfdb.untils.HttpClientUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author l
* @version 1.0
* @date 2021/11/10 14:16 周三
测试
*/
@RestController
public class H5FaceLivingController extends AbstractController{
/**
* 视频活体识别接⼝
* @param callback
* @return
*/
@RequestMapping(value = "/H5faceLiving", method = RequestMethod.GET)
public String H5faceLiving(@RequestParam("callback") String callback) {
Map<String, Object> map = new HashMap<>(5);
String url="http://ip:8300/face-api/face/session?type=1&min_code_length=1&max_code_length=3";
JSONObject jsonObject = HttpClientUtils.httpGet(url);
H5FacelivingRoot h5FacelivingRoot = JSONUtil.toBean(jsonObject.toJSONString(), H5FacelivingRoot.class);
map.put( "err_no", h5FacelivingRoot.getErr_no() );
map.put( "err_msg", h5FacelivingRoot.getErr_msg());
map.put( "data", h5FacelivingRoot.getResult());
return callback+"("+JSONObject.toJSONString(map)+")";
}
/**
* 视频活体检测
* @return
*/
@RequestMapping(value = "/videoDetection", method = RequestMethod.POST)
public Map<String, String> videoDetection(HttpServletRequest request) {
Map<String, String> map = new HashMap<>(5);
String url="http://ip:8300/face-api/face/liveness";
Map<String, String> paramMap=new HashMap<>(3);
MultipartFile file =null;
BASE64Encoder base64Encoder =null;
try {
//接收会话id
String session_id = request.getParameter("session_id");
//获取视频文件
MultipartHttpServletRequest mureq = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> files = mureq.getFileMap();
if (files != null &&files.size()> 0) {
Map.Entry<String, MultipartFile> f = files.entrySet().iterator().next();
file = f.getValue();
}
//将MultipartFile转成base64视频流
base64Encoder =new BASE64Encoder();
String base64EncoderImg = base64Encoder.encode(file.getBytes());
//请求视频活体检测参数
paramMap.put("session_id", session_id);
paramMap.put("type_identify","action");
paramMap.put("video_base64", base64EncoderImg);
System.out.println("session_id=="+session_id);
//请求
JSONObject jsonObject = HttpClientUtils.httpPostFrom(url,paramMap,null);
String err_no = jsonObject.getString("err_no");
String err_msg = jsonObject.getString("err_msg");
System.out.println("err_no=="+err_no);
System.out.println("err_msg=="+err_msg);
map.put("err_no", err_no);
map.put("err_msg", err_msg);
}catch (IOException e){
logger.error("视频活体检测失败:"+e.getMessage());
}
return map;
}
}
<!DOCTYPE html>
<html>
<head>
<title>video recoder</title>
<script src="/fileSaver.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/buijs@latest/lib/latest/bui.css">
<link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
</head>
<style>
body {
background-color: #EFEDEF;
}
video {
aspect-ratio: auto !important;
object-fit: fill !important;
border-radius: 50%;
}
header.bui-bar,
header .bui-bar {
background-color: white;
}
header.bui-bar .bui-bar-main,
header .bui-bar .bui-bar-main {
color: black;
}
.peopleimg {
margin-top: 10%;
display: flex;
justify-content: center;
}
.info {
background-color: #4DC3D3;
border: #4DC3D3;
margin-top: 6%;
width: 90% !important;
}
.experiment {
display: flex;
justify-content: space-around;
}
#close {
font-family: PingFang SC;
font-weight: 500;
line-height: 45px;
color: #FFFFFF;
opacity: 1;
display: inline-block;
line-height: 3rem;
}
#faceInfoH5 {
font-family: PingFang SC;
font-weight: 500;
line-height: 45px;
color: #ff0202;
opacity: 1;
display: flex;
justify-content: center;
/* display: inline-block; */
line-height: 3rem;
}
#save-recording {
font-family: PingFang SC;
font-weight: 500;
line-height: 45px;
color: #FFFFFF;
opacity: 1;
display: inline-block;
line-height: 3rem;
}
#Recording {
display: inline-block;
width: 3rem;
height: 3rem;
border: 0.2rem solid #ffffff;
border-radius: 50%;
}
#Recordingbox {
width: 2rem;
height: 2rem;
background: #4DC3D3;
border-radius: 50%;
opacity: 1;
margin: auto;
margin-top: 10%;
}
</style>
<body>
<header class="bui-bar">
<div class="bui-bar-left bui-bar-text">
<a class="bui-btn"><i class="icon-back" style="color: black;"></i>返回</a>
</div>
<div class="bui-bar-main">人脸录制</div>
<div class="bui-bar-right bui-bar-text">
</div>
</header>
<div class="peopleimg">
<img src="/people.png" style="width: 8rem;height: 8rem;">
</div>
<div class="bui-btn info" id="openCamera">打开摄像头</div>
<article class="articlebox"
style="width:400px;height:100%; background-color: black; margin:0 auto; display: none; ">
<span id="faceInfoH5"></span>
<section class="experiment"
style="width:240px; height:240px;border-radius:50%;background-color: white; margin:50px auto; margin-top: 20px;">
<div id="videos-container" style="width:240px; height:240px;">
</div>
</section>
<section class="experiment" style="text-align:center;border:none; margin-top:20px;">
<!-- <span id="close">取消</span> -->
<!-- <span id="faceInfoH5"></span> -->
<div id="Recording">
<div id="Recordingbox">
<div id="start-recording" style="position: relative;top: 36%;"><span id="startcordtext">开始录制</span>
</div>
</div>
</div>
<!-- <span id="save-recording">保存</span> -->
<!-- <button id="start-recording" disabled>开始录制</button> -->
<!-- <button id="save-recording" disabled>保存</button> -->
<!--<a href="javascript:void(0)" onclick="send()">发送</a>-->
</section>
</article>
<script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script>
<script>
// bui.ready(function () {
layui.use(['layer', 'form'], function () {
var layer = layui.layer;
var $ = layui.jquery;
var mediaStream;
var recorderFile;
var stopRecordCallback;
var session_id;
// var baseUrldd = 'http://10.108.234.253:8300';
// $(".info").click(function (e) {
// e.preventDefault();
// });
var openBtn = document.getElementById("openCamera");
var startBtn = document.getElementById("start-recording");
// var saveBtn = document.getElementById("save-recording");
openBtn.onclick = function () {
$(this).hide()
// .style.display = 'none';
// .style.display = 'block';
$(".peopleimg").hide();
$(".articlebox").show();
this.disabled = true;
startBtn.disabled = false;
openCamera();
};
startBtn.onclick = function () {
this.disabled = true;
$("#startcordtext").text("录制中")
$("#startcordtext").css("color", "#ff7300")
startRecord();
};
// saveBtn.onclick = function () {
// saver();
// this.disabled = true;
// // alert('Drop WebM file on Chrome or Firefox. Both can play entire file. VLC player or other players may not work.');
// };
var mediaRecorder;
var videosContainer = document.getElementById('videos-container');
function openCamera() {
//请求视频活体识别接⼝
$.ajax({
type: "GET",
url: "http://127.0.0.1:12667/H5faceLiving",
dataType: "jsonp",//数据类型为jsonp
jsonp: "tt",//服务端用于接收callback调用的function名的参数
success: function (data) {
var code, loveArr, msg0;
console.log(data);
if (data.err_no === 0) {
//返回值的代表所需动作和动作顺序。0:眨眼 2:右转 3:左 转 4:抬头 5:低头
code = data.data.code;
//会话ID
session_id = data.data.session_id;
//切割
loveArr = code.split('');
// console.log(loveArr);
//【0:眨眼 2:右转 3:左转 4:抬头 5:低头】
for (let i = 0; i < loveArr.length; i++) {
if (loveArr[i] === '0') {
msg0 = '眨眼';
console.log(msg0);
$("#faceInfoH5").append(msg0 + " ");
} else if (loveArr[i] === '2') {
msg0 = '右转';
console.log(msg0);
$("#faceInfoH5").append(msg0 + " ");
} else if (loveArr[i] === '3') {
msg0 = '左转';
console.log(msg0);
$("#faceInfoH5").append(msg0 + " ");
} else if (loveArr[i] === '4') {
msg0 = '抬头';
console.log(msg0);
$("#faceInfoH5").append(msg0 + " ");
} else if (loveArr[i] === '5') {
msg0 = '低头';
console.log(msg0);
$("#faceInfoH5").append(msg0 + " ");
}
};
} else {
alert('调用活体接口失败');
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(textStatus);
}
});
var len = videosContainer.childNodes.length;
for (var i = 0; i < len; i++) {
videosContainer.removeChild(videosContainer.childNodes[i]);
}
var video = document.createElement('video');
var videoWidth = 240;
var videoHeight = 240;
video.controls = false;
video.muted = true;
video.width = videoWidth;
video.height = videoHeight;
MediaUtils.getUserMedia(true, false, function (err, stream) {
if (err) {
throw err;
} else {
// 通过 MediaRecorder 记录获取到的媒体流
console.log();
mediaRecorder = new MediaRecorder(stream);
mediaStream = stream;
var chunks = [], startTime = 0;
video.srcObject = stream;
video.play();
videosContainer.appendChild(video);
mediaRecorder.ondataavailable = function (e) {
mediaRecorder.blobs.push(e.data);
chunks.push(e.data);
};
mediaRecorder.blobs = [];
mediaRecorder.onstop = function (e) {
recorderFile = new Blob(chunks, { 'type': mediaRecorder.mimeType });
chunks = [];
if (null != stopRecordCallback) {
stopRecordCallback();
}
};
}
});
}
function tt(data) {
console.log(data);
}
// 停止录制
function stopRecord(callback) {
stopRecordCallback = callback;
// 终止录制器
mediaRecorder.stop();
// 关闭媒体流
MediaUtils.closeStream(mediaStream);
}
var MediaUtils = {
/**
* 获取用户媒体设备(处理兼容的问题)
* @param videoEnable {boolean} - 是否启用摄像头
* @param audioEnable {boolean} - 是否启用麦克风
* @param callback {Function} - 处理回调
*/
getUserMedia: function (videoEnable, audioEnable, callback) {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
|| navigator.msGetUserMedia || window.getUserMedia;
var constraints = { video: videoEnable, audio: audioEnable };
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
callback(false, stream);
})['catch'](function (err) {
callback(err);
});
} else if (navigator.getUserMedia) {
navigator.getUserMedia(constraints, function (stream) {
callback(false, stream);
}, function (err) {
callback(err);
});
} else {
callback(new Error('Not support userMedia'));
}
},
/**
* 关闭媒体流
* @param stream {MediaStream} - 需要关闭的流
*/
closeStream: function (stream) {
if (typeof stream.stop === 'function') {
stream.stop();
}
else {
let trackList = [stream.getAudioTracks(), stream.getVideoTracks()];
for (let i = 0; i < trackList.length; i++) {
let tracks = trackList[i];
if (tracks && tracks.length > 0) {
for (let j = 0; j < tracks.length; j++) {
let track = tracks[j];
if (typeof track.stop === 'function') {
track.stop();
}
}
}
}
}
}
};
function startRecord() {
// debugger
mediaRecorder.start();
setTimeout(function () {
// 结束
stopRecord(function () {
// alert("录制成功!");
openBtn.disabled = false;
// saveBtn.disabled = false;
// send();
saver();
});
}, 5000);
}
function saver() {
var file = new File([recorderFile], 'msr-' + (new Date).toISOString().replace(/:|\./g, '-') + '.mp4', {
type: 'video/mp4'
});
// console.log(file);
//定义一个formData,便于传输file参数
//视频活体检测
var formData = new FormData();
formData.append('file', file);
formData.append('session_id', session_id);
$("#startcordtext").text("正在检测中")
$("#startcordtext").css("color", "red")
$("#startcordtext").css("font-weight", "600")
$.ajax({
url: "http://127.0.0.1:12667/videoDetection",
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false,
success: function (data) {
if (data.err_no === '0') {
// alert("活体认证成功");
layer.msg("活体认证成功")
} else {
layer.msg("活体认证失败" + "," + data.err_msg)
// alert("活体认证失败"+","+data.err_msg);
}
},
error: function (res) {
console.log(res);
}
});
// saveAs(file);
}
function send() {
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("userfile", file);
var req = new XMLHttpRequest();
req.open("POST", "com.spinsoft.bip.frame.utils.image.saveMp4.biz.ext");
req.send(data);
}
});
</script>
</body>
</html>