123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- // pages/faceRecognition/index.ts
- import { base } from "../../config/index";
- 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;
- let notify = ""
- const daoJiShi: number = 15;
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- isStartVideo: false, // 是否点击开始按钮
- isEmpower: false, // 是否授权
- isUpLoad: false, // 是否上传中
- initFace: false, // 是否初始化人脸识别
- isTranscribe: false, // 是否录制中
- seconds: 0, // 倒计
- topTips: topTips.ready, // 提示语句
- bottomTips: "", // 底部提示语句
- buttomText: "录制"
- },
- // 开始初始化录制
- async initCamera() {
- if (this.data.isStartVideo) return;
- wx.showLoading({
- title: ""
- })
- this.setData({
- isStartVideo: true
- })
- wx.nextTick(() => {
- this.getMssage().then(async (r: any) => {
- console.log('是否授权发送消息:', r);
- notify = 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() {
- // 初始化人脸识别
- if (this.data.initFace) return this.addListen();
- if (!createVKSession) createVKSession = wx.createVKSession({
- version: "v1",
- track: {
- plane: {
- mode: 1
- },
- face: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
- },
- })
- // 静态图片检测模式下,每调一次 detectFace 接口就会触发一次 updateAnchors 事件
- createVKSession?.on('updateAnchors', (anchors)=> {
- for (let I = 0; I < anchors.length; I++) {
- const anchor = anchors[I];
- const W = anchor.size.width * 100;
- let titlet = "";
- if(W < 20 || W > 80 ) titlet = "请远离屏幕"
- if(W < 20) titlet = "请靠近屏幕"
- titlet && wx.showToast({
- icon: "none",
- title: titlet
- })
- }
- })
- createVKSession?.on('removeAnchors', () => {
- wx.showToast({
- title: "未检测到人脸, 请重新采集",
- icon: "error"
- });
- this.overVideo();
- })
- this.addListen();
- },
- // 结束录像
- overVideo() {
- if (!ctx || !this.data.isStartVideo) return;
- ctx.stopRecord({
- compressed: true,
- complete: () => {
- createVKSession?.stop();
- innerAudioContext?.pause();
- listener?.stop();
- this.setData({
- isStartVideo: false,
- bottomTips: "",
- topTips: topTips.ready,
- seconds: 0
- })
- }
- })
- },
- // 获取本地临时地址
- getUrl(res: WechatMiniprogram.StartRecordTimeoutCallbackResult) {
- this.setData({
- isUpLoad: true
- })
- wx.showLoading({
- title: '上传进度:0%',
- mask: true //是否显示透明蒙层,防止触摸穿透
- })
- const uploadTask = wx.uploadFile({
- url: base.url + '/v3/upload',
- filePath: res.tempVideoPath,
- name: 'file', //服务器定义的Key值
- formData: {
- notify
- },
- header: {
- Authorization: wx.getStorageSync("token")
- },
- 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: () => {
- wx.hideLoading();
- wx.showToast({
- title: "上传失败",
- icon: "none",
- duration: 2000
- })
- this.setData({
- topTips: topTips.ready, // 提示语句
- bottomTips: bottomTips.error
- })
- },
- complete: () => {
- this.setData({
- isUpLoad: false
- })
- }
- })
- //监听上传进度变化事件
- uploadTask.onProgressUpdate((res) => {
- wx.showLoading({
- title: '上传进度:' + res.progress + '%',
- mask: true //是否显示透明蒙层,防止触摸穿透
- })
- })
- },
- // 非正常中止
- improperStop() {
- wx.navigateBack();
- },
- // 未授权
- 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() {
- innerAudioContext = wx.createInnerAudioContext();
- innerAudioContext.loop = false;
- },
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady() {
- },
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
- },
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide() {
- // 在录制中退出后台页面隐藏,返回上一页,确保重新进入当前页
- this.overVideo();
- },
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload() {
- },
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
- },
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
- },
- /**
- * 用户点击右上角分享
- */
- // onShareAppMessage() {
- // },
- })
- export { }
|