|
@@ -1,9 +1,23 @@
|
|
|
// pages/faceRecognition/index.ts
|
|
|
import { base } from "../../config/index";
|
|
|
-import { compareVersion } from "../../utils/util";
|
|
|
let ctx: WechatMiniprogram.CameraContext | undefined = undefined;
|
|
|
+let listener: WechatMiniprogram.CameraFrameListener | undefined;
|
|
|
let createVKSession: WechatMiniprogram.VKSession | undefined = undefined;
|
|
|
+let innerAudioContext: WechatMiniprogram.InnerAudioContext;
|
|
|
const app = getApp<IAppOption>();
|
|
|
+const topTips = {
|
|
|
+ ready: '请正对手机,保持光线充足',
|
|
|
+ front: '请正对屏幕',
|
|
|
+ left: '请向左转头',
|
|
|
+ right: '请向右转头',
|
|
|
+}
|
|
|
+const bottomTips = {
|
|
|
+ recording: '脸部信息录入中...',
|
|
|
+ complete: '脸部信息录入成功',
|
|
|
+ error: '脸部信息录入失败'
|
|
|
+}
|
|
|
+let T: number = 0;
|
|
|
+const daoJiShi: number = 15;
|
|
|
Page({
|
|
|
|
|
|
/**
|
|
@@ -13,128 +27,154 @@ Page({
|
|
|
isStartVideo: false, // 是否点击开始按钮
|
|
|
isEmpower: false, // 是否授权
|
|
|
isUpLoad: false, // 是否上传中
|
|
|
+ initFace: false, // 是否初始化人脸识别
|
|
|
isTranscribe: false, // 是否录制中
|
|
|
-
|
|
|
+ seconds: 0, // 倒计
|
|
|
+ topTips: topTips.ready, // 提示语句
|
|
|
+ bottomTips: "", // 底部提示语句
|
|
|
buttomText: "录制"
|
|
|
},
|
|
|
|
|
|
// 开始初始化录制
|
|
|
- initCamera() {
|
|
|
+ async initCamera() {
|
|
|
if (this.data.isStartVideo) return;
|
|
|
+ wx.showLoading({
|
|
|
+ title: ""
|
|
|
+ })
|
|
|
this.setData({
|
|
|
isStartVideo: true
|
|
|
})
|
|
|
wx.nextTick(() => {
|
|
|
- this.createVK();
|
|
|
- wx.showLoading({
|
|
|
- title: ""
|
|
|
- })
|
|
|
- ctx = wx.createCameraContext();
|
|
|
- ctx.startRecord({
|
|
|
- timeout: 15, // 录制时长
|
|
|
- timeoutCallback: () => {
|
|
|
- // 超出录制时长 关闭录屏
|
|
|
- this.overVideo();
|
|
|
- },
|
|
|
- success: () => {
|
|
|
- // 调用成功,开始录制
|
|
|
- wx.hideLoading();
|
|
|
- },
|
|
|
- fail: () => {
|
|
|
- // 调用失败
|
|
|
- wx.hideLoading();
|
|
|
- wx.showToast({
|
|
|
- icon: "none",
|
|
|
- title: "相机调用失败",
|
|
|
- duration: 2000
|
|
|
- })
|
|
|
- },
|
|
|
- complete: () => { }
|
|
|
- })
|
|
|
+ this.getMssage().then(async (r: any) => {
|
|
|
+ console.log('是否授权发送消息:', r)
|
|
|
+ if (!ctx) ctx = wx.createCameraContext();
|
|
|
+ this.createVK();
|
|
|
+ ctx.startRecord({
|
|
|
+ timeout: daoJiShi, // 录制时长
|
|
|
+ selfieMirror: false,
|
|
|
+ timeoutCallback: (res) => {
|
|
|
+ // 超出录制时长 关闭录屏
|
|
|
+ this.setData({
|
|
|
+ isStartVideo: false,
|
|
|
+ bottomTips: "",
|
|
|
+ topTips: topTips.ready, // 提示语句
|
|
|
+ })
|
|
|
+ createVKSession?.stop();
|
|
|
+ listener?.stop();
|
|
|
+ this.getUrl(res);
|
|
|
+ },
|
|
|
+ success: () => {
|
|
|
+ // 调用成功,开始录制
|
|
|
+ wx.hideLoading();
|
|
|
+ this.setData({
|
|
|
+ seconds: daoJiShi,
|
|
|
+ bottomTips: bottomTips.recording,
|
|
|
+ topTips: topTips.front
|
|
|
+ });
|
|
|
+ innerAudioContext.src = "assets/voice/front.mp3";
|
|
|
+ innerAudioContext.play();
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ // 调用失败
|
|
|
+ wx.hideLoading();
|
|
|
+ wx.showToast({
|
|
|
+ icon: "none",
|
|
|
+ title: "相机调用失败",
|
|
|
+ duration: 2000
|
|
|
+ })
|
|
|
+ },
|
|
|
+ complete: () => { }
|
|
|
+ })
|
|
|
+ });
|
|
|
})
|
|
|
},
|
|
|
+ // 添加监听
|
|
|
+ addListen() {
|
|
|
+ createVKSession?.start(() => { });
|
|
|
+ T = Date.now();
|
|
|
+ !listener && (listener = ctx?.onCameraFrame((frame: any) => {
|
|
|
+ const Time = daoJiShi * 1000 - (Date.now() - T);
|
|
|
+ if (Time % 1000 >= 50) return
|
|
|
+ const s = Math.floor(Time / 1000);
|
|
|
+ if (s == 10) {
|
|
|
+ innerAudioContext.src = "assets/voice/left.mp3";
|
|
|
+ this.setData({
|
|
|
+ topTips: topTips.left
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (s == 5) {
|
|
|
+ innerAudioContext.src = "assets/voice/right.mp3";
|
|
|
+ this.setData({
|
|
|
+ topTips: topTips.right
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (s % 5 === 0 && s !== 0) innerAudioContext.play();
|
|
|
+ this.setData({
|
|
|
+ seconds: s
|
|
|
+ })
|
|
|
|
|
|
+ // 识别人脸是否在画面种
|
|
|
+ createVKSession?.detectFace({
|
|
|
+ frameBuffer: frame.data, // 图片 ArrayBuffer 数据。人脸图像像素点数据,每四项表示一个像素点的 RGBA
|
|
|
+ width: frame.width, // 图像宽度
|
|
|
+ height: frame.height, // 图像高度
|
|
|
+ scoreThreshold: 0.5, // 评分阈值
|
|
|
+ sourceType: 1
|
|
|
+ })
|
|
|
+ }));
|
|
|
+ listener?.start();
|
|
|
+ },
|
|
|
// 创建人脸追踪
|
|
|
createVK() {
|
|
|
- console.log("开始追踪人脸");
|
|
|
- createVKSession = wx.createVKSession({
|
|
|
+ // 初始化人脸识别
|
|
|
+ if (this.data.initFace) return this.addListen();
|
|
|
+ if (!createVKSession) createVKSession = wx.createVKSession({
|
|
|
version: "v1",
|
|
|
track: {
|
|
|
plane: {
|
|
|
- mode: 3
|
|
|
- },
|
|
|
- face: {
|
|
|
mode: 1
|
|
|
- }
|
|
|
+ },
|
|
|
+ face: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
|
|
|
},
|
|
|
})
|
|
|
-
|
|
|
- createVKSession.on("updateAnchors", anchors => {
|
|
|
- console.log("检测到人脸", anchors)
|
|
|
- if (!this.data.isTranscribe) {
|
|
|
- this.setData({
|
|
|
- isTranscribe: true
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- // 当人脸从相机中离开时,会触发 removeAnchors 事件
|
|
|
- createVKSession.on('removeAnchors', () => {
|
|
|
+ // 静态图片检测模式下,每调一次 detectFace 接口就会触发一次 updateAnchors 事件
|
|
|
+ createVKSession?.on('removeAnchors', () => {
|
|
|
wx.showToast({
|
|
|
- icon: "none",
|
|
|
- title: "未检测到人脸,请重新录制",
|
|
|
- duration: 2000
|
|
|
- })
|
|
|
- // 录制失败
|
|
|
+ title: "未检测到人脸, 请重新采集",
|
|
|
+ icon: "error"
|
|
|
+ });
|
|
|
this.overVideo();
|
|
|
})
|
|
|
-
|
|
|
- createVKSession.start((errno) => {
|
|
|
- console.log(errno);
|
|
|
- })
|
|
|
+ this.addListen();
|
|
|
},
|
|
|
-
|
|
|
// 结束录像
|
|
|
overVideo() {
|
|
|
if (!ctx || !this.data.isStartVideo) return;
|
|
|
- wx.showLoading({
|
|
|
- title: ""
|
|
|
- })
|
|
|
- createVKSession?.stop();
|
|
|
ctx.stopRecord({
|
|
|
compressed: true,
|
|
|
- success: res => {
|
|
|
- // 成功结束
|
|
|
- wx.hideLoading();
|
|
|
- this.getUrl(res);
|
|
|
- },
|
|
|
- fail: () => {
|
|
|
- // 结束失败
|
|
|
- wx.hideLoading();
|
|
|
- wx.showToast({
|
|
|
- icon: "none",
|
|
|
- title: "相机关闭失败",
|
|
|
- duration: 2000
|
|
|
- })
|
|
|
- },
|
|
|
complete: () => {
|
|
|
+ createVKSession?.stop();
|
|
|
+ innerAudioContext?.pause();
|
|
|
+ listener?.stop();
|
|
|
this.setData({
|
|
|
- isStartVideo: false
|
|
|
+ isStartVideo: false,
|
|
|
+ bottomTips: "",
|
|
|
+ topTips: topTips.ready,
|
|
|
+ seconds: 0
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
-
|
|
|
// 获取本地临时地址
|
|
|
getUrl(res: WechatMiniprogram.StartRecordTimeoutCallbackResult) {
|
|
|
this.setData({
|
|
|
isUpLoad: true
|
|
|
})
|
|
|
wx.showLoading({
|
|
|
- title: ""
|
|
|
+ title: '上传进度:0%',
|
|
|
+ mask: true //是否显示透明蒙层,防止触摸穿透
|
|
|
})
|
|
|
- wx.uploadFile({
|
|
|
- // 仅为示例,非真实的接口地址,视频上传
|
|
|
+ const uploadTask = wx.uploadFile({
|
|
|
url: base.url + '/v3/upload',
|
|
|
filePath: res.tempVideoPath,
|
|
|
name: 'file', //服务器定义的Key值
|
|
@@ -142,23 +182,35 @@ Page({
|
|
|
header: {
|
|
|
Authorization: wx.getStorageSync("token")
|
|
|
},
|
|
|
- success: function (res) {
|
|
|
- console.log(res)
|
|
|
+ success: () => {
|
|
|
wx.hideLoading();
|
|
|
wx.showToast({
|
|
|
title: "上传成功",
|
|
|
duration: 2000,
|
|
|
icon: "none"
|
|
|
+ });
|
|
|
+ this.setData({
|
|
|
+ topTips: topTips.ready, // 提示语句
|
|
|
+ bottomTips: bottomTips.complete
|
|
|
})
|
|
|
+ let time = setTimeout(() => {
|
|
|
+ clearTimeout(time);
|
|
|
+ wx.reLaunch({
|
|
|
+ url: "/pages/downloadPage/index"
|
|
|
+ })
|
|
|
+ }, 2000)
|
|
|
},
|
|
|
- fail: function (res) {
|
|
|
- console.log(res)
|
|
|
+ fail: () => {
|
|
|
wx.hideLoading();
|
|
|
wx.showToast({
|
|
|
title: "上传失败",
|
|
|
icon: "none",
|
|
|
duration: 2000
|
|
|
})
|
|
|
+ this.setData({
|
|
|
+ topTips: topTips.ready, // 提示语句
|
|
|
+ bottomTips: bottomTips.error
|
|
|
+ })
|
|
|
},
|
|
|
complete: () => {
|
|
|
this.setData({
|
|
@@ -166,24 +218,51 @@ Page({
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
+ //监听上传进度变化事件
|
|
|
+ uploadTask.onProgressUpdate((res) => {
|
|
|
+ wx.showLoading({
|
|
|
+ title: '上传进度:' + res.progress + '%',
|
|
|
+ mask: true //是否显示透明蒙层,防止触摸穿透
|
|
|
+ })
|
|
|
+ })
|
|
|
},
|
|
|
-
|
|
|
// 非正常中止
|
|
|
- improperStop() { },
|
|
|
-
|
|
|
+ improperStop() {
|
|
|
+ wx.navigateBack();
|
|
|
+ },
|
|
|
// 未授权
|
|
|
- unauthorized() { },
|
|
|
-
|
|
|
+ unauthorized() {
|
|
|
+ wx.showToast({
|
|
|
+ title: "拒绝授权将无法录制视频信息"
|
|
|
+ });
|
|
|
+ wx.navigateBack();
|
|
|
+ },
|
|
|
// 初始化完成
|
|
|
initialization() { },
|
|
|
-
|
|
|
+ // 获取消息授权
|
|
|
+ getMssage() {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ if (!app.globalData.configPage?.messageID || !wx.canIUse("requestSubscribeMessage")) {
|
|
|
+ resolve("reject");
|
|
|
+ return
|
|
|
+ }
|
|
|
+ wx.requestSubscribeMessage({
|
|
|
+ tmplIds: app.globalData.configPage?.messageID || [],
|
|
|
+ success: (res: WechatMiniprogram.RequestSubscribeMessageSuccessCallbackResult) => {
|
|
|
+ resolve(res.p1mpCydIQ6OtxCSa62NaSFiEkQiTsb8KPFaAs1SuKMw || 'reject');
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ resolve("reject");
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
/**
|
|
|
* 生命周期函数--监听页面加载
|
|
|
*/
|
|
|
- onLoad(opt) {
|
|
|
- console.log(opt)
|
|
|
- const SDKVersion: string = app.globalData.SystemInfo?.SDKVersion || "";
|
|
|
- compareVersion(SDKVersion, '1.9.6');
|
|
|
+ onLoad() {
|
|
|
+ innerAudioContext = wx.createInnerAudioContext();
|
|
|
+ innerAudioContext.loop = false;
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -204,6 +283,7 @@ Page({
|
|
|
*/
|
|
|
onHide() {
|
|
|
// 在录制中退出后台页面隐藏,返回上一页,确保重新进入当前页
|
|
|
+ this.overVideo();
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -230,9 +310,9 @@ Page({
|
|
|
/**
|
|
|
* 用户点击右上角分享
|
|
|
*/
|
|
|
- onShareAppMessage() {
|
|
|
+ // onShareAppMessage() {
|
|
|
|
|
|
- },
|
|
|
+ // },
|
|
|
})
|
|
|
|
|
|
export { }
|