Browse Source

播放视频,需要人脸认证

y595705120 1 year ago
parent
commit
a394eb9615

+ 102 - 41
src/containers/center/play/components/iMedia.vue

@@ -9,8 +9,11 @@
       <el-col :span="18" style="width:680px;">
 
         <div style="height: 540px;">
-        <video-player id="myVideo" class="video-player-box" ref="videoPlayer" :playsinline="true"
-          @pause="onPlayerPause($event)" @play="onPlayerStart($event)" @ready="playerReadied"
+        <video-player id="myVideo" class="video-player-box" ref="videoPlayer"
+
+          @pause="onPlayerPause($event)"
+          @play="onPlayerStart($event)"
+          @ready="playerReadied"
           @timeupdate="onPlayerTimeupdate($event)" @ended="onPlayerEnded($event)" :globalOptions="{controls:true}"
           :options="options">
         </video-player>
@@ -40,7 +43,7 @@
               <div class="sub-list" v-if="item.name==activeChapter">
                 <a v-for="(subItem,index)  in list" :key="subItem.id" v-if="subItem.chapterName == activeChapter"
                   @click="goSubState(subItem, index)" :class="{'current':subItem.name==activeName}">
-                  <span style="width: 8px;height: 8px;">
+                  <span class="media-process">
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
                       :format="()=>{return ''}" v-if="subItem.percent>=100" color="green"></el-progress>
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
@@ -48,7 +51,7 @@
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
                       :format="()=>{return ''}" v-else></el-progress>
                   </span>
-                  <span style="margin-left: 16px;"> {{subItem.name}} </span>
+                  <span class="media-name"> {{subItem.name}} </span>
                 </a>
               </div>
             </li>
@@ -64,7 +67,7 @@
               <div class="sub-list pt10" v-if="item.name==activeChapter">
                 <a v-for="(subItem,index) in list" :key="subItem.id" v-if="subItem.chapterName == activeChapter"
                   @click="goSubState(subItem, index)" :class="{'current':subItem.name==activeName}">
-                  <span style="width: 8px;height: 8px;">
+                  <span class="media-process">
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
                       :format="()=>{return ''}" v-if="subItem.percent>=100" color="green"></el-progress>
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
@@ -72,7 +75,7 @@
                     <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"
                       :format="()=>{return ''}" v-else></el-progress>
                   </span>
-                  <span style="margin-left: 16px;"> {{subItem.name}} </span>
+                  <span  class="media-name"> {{subItem.name}} </span>
                 </a>
                 </a>
               </div>
@@ -88,11 +91,19 @@
       </el-col>
 
     </el-row>
-    <div class="left-float" v-if="!closeFace" v-drag>
-      <video ref="video" v-show="isnotbtn" width="240" height="180" autoplay></video>
+    <div class="left-float" v-if="!closeFace" v-drag v-show="identifyFacePass">
+      <video ref="video"  width="240" height="180" autoplay></video>
       <canvas ref="canvas" v-show="ontakebtn" width="240" height="180"></canvas>
     </div>
 
+    <el-dialog title="人脸认证" center :visible.sync="identifyFace" width="500px" :close-on-click-modal="false">
+      <div style="width: 240px;margin: 100px auto;">
+        <video ref="video2"  width="240" height="180" autoplay></video>
+        <p  style="margin-top: 20px;">当前照片:</p>
+        <canvas ref="canvas" width="240" height="180"></canvas>
+        <p v-if="errMsg" style="font-size: 30px;color: red;"> {{errMsg}}</p>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -121,8 +132,9 @@
         tickNum: 0,
         prevTime: 0,
         isReady: false,
-        isnotbtn: false,
         ontakebtn: false,
+        identifyFace: false,
+        identifyFacePass: false,
         activeChapter: '',
         activeName: '',
         curTimes: 0,
@@ -174,7 +186,7 @@
     },
     beforeDestroy() {
       this.destroyTimer()
-      this.closeCamera()
+      this.closeCamera( "video" )
     },
     created() {
       this.startTick()
@@ -189,21 +201,24 @@
         this.tickNum = 0
         this.errMsg = ''
         this.errCount = 0
+        this.startIdentify()
         this.setposition( this.media.position )
       }
     },
     methods: {
-      photograph() {
+      photograph( ref ) {
+        let identify = (ref=="video2");
         let ctx = this.$refs["canvas"].getContext("2d");
         // 把当前视频帧内容渲染到canvas上
         this.ontakebtn = true
-        ctx.drawImage(this.$refs["video"], 0, 0, 240, 180);
+        ctx.drawImage(this.$refs[ref], 0, 0, 240, 180);
         // 转base64格式、图片格式转换、图片质量压缩
         let imgBase64 = this.$refs["canvas"].toDataURL("image/jpeg", 1); // 由字节转换为KB 判断大小
         this.ontakebtn = false
         let str = imgBase64.replace("data:image/jpeg;base64,", "");
         let param = {
           id: this.media.id,
+          ref,
           image: str
         }
         httpServer("course.collect", param).then(res => {
@@ -215,9 +230,12 @@
           if (msg) {
             this.errCount++
           } else {
+            if( identify ){
+              this.identifyPassAndPlay()
+            }
             this.errCount = 0;
           }
-          if (this.errCount > this.maxErrorCount) {
+          if (!identify && this.errCount > this.maxErrorCount) {
             this.doPause();
           }
         })
@@ -235,10 +253,10 @@
       goSubState(item, index) {
         this.$emit('loadMedia', item, index)
       },
-      callCamera() {
+      callCamera( ref ) {
         // H5调用电脑摄像头API
         if (this.closeFace) {
-          this.isnotbtn = true;
+          this.identifyFacePass = true;
           return;
         }
         navigator.mediaDevices
@@ -246,31 +264,27 @@
             video: true,
           })
           .then((success) => {
-            this.isnotbtn = true
             // 摄像头开启成功
-            this.$refs["video"].srcObject = success;
+            this.$refs[ref].srcObject = success;
             // 实时拍照效果
-            this.$refs["video"].play();
+            this.$refs[ref].play();
           })
           .catch((error) => {
             this.$message.error(
               "摄像头开启失败,请检查摄像头是否可用!或者打开摄影头"
             );
-            this.isnotbtn = false
             console.error("摄像头开启失败,请检查摄像头是否可用!");
           });
       },
-      closeCamera() {
-        console.log("closeCamera")
-        if (!this.$refs["video"]) return;
-        if (!this.$refs["video"].srcObject) return;
-        let stream = this.$refs["video"].srcObject;
+      closeCamera( ref ) {
+        if (!this.$refs[ref]) return;
+        if (!this.$refs[ref].srcObject) return;
+        let stream = this.$refs[ref].srcObject;
         let tracks = stream.getTracks();
         tracks.forEach((track) => {
           track.stop();
         });
-        this.$refs["video"].srcObject = null;
-        this.isnotbtn = false
+        this.$refs[ref].srcObject = null;
       },
       startTick() {
         let tick = this.tryTick;
@@ -302,7 +316,6 @@
             this.setposition(position)
           }, 2000)
         }
-        this.callCamera()
         this.isReady = true
       },
       onPlayerTimeupdate(player) {
@@ -328,7 +341,6 @@
       },
       onPlayerPause(event) {
         this.reportErr("play", 'pause');
-        this.stopTick()
         this.onPlay = false
       },
       onPlayerEnded(event) {
@@ -339,10 +351,9 @@
         this.reportErr("play", 'close')
         this.doPause()
         this.$emit("close")
-        this.closeCamera()
+        this.closeCamera( "video")
       },
       doPause() {
-        this.stopTick()
         this.onPlay = false
         let myPlayer = this.$refs.videoPlayer.player;
         myPlayer && myPlayer.pause()
@@ -356,12 +367,29 @@
         myPlayer && myPlayer.play()
         this.tickNum = 0
       },
-      onPlayerStart() {
+      onPlayerStart( player ) {
         console.log("onPlayerStart")
+        this.onPlay = true
+        if( !this.identifyFacePass){
+          this.startIdentify()
+        }
         this.reportErr("play", 'start');
         this.startTick();
-        this.onPlay = true
-        this.tickNum = 0
+      },
+      startIdentify(){
+        this.identifyFace = true
+        this.identifyFacePass = false
+        this.closeCamera("video")
+        this.callCamera("video2")
+        this.startTick()
+      },
+      identifyPassAndPlay(){
+        this.identifyFacePass = true
+        this.identifyFace = false;
+        this.closeCamera("video2")
+        this.callCamera("video")
+        this.$message.successMsg("人脸认证通过", 2)
+        this.doPlay()
       },
       reportErr(action, msg) {
         httpServer("course.report", {
@@ -385,6 +413,21 @@
       tick(force = false) {
         let media = this.media;
         this.tickNum++
+        // 人脸认证期间
+        if( !this.identifyFacePass ) {
+          if( this.onPlay ){
+            this.doPause()
+          }
+          // 人脸认证
+          if (this.tickNum % 3 == 1) {
+            this.photograph( "video2" );
+          }
+          return;
+        };
+        // 未开始
+        if(!force && !this.onPlay ){
+          return;
+        }
 
         // 已经完成
         if (this.media.isFinish) {
@@ -395,12 +438,12 @@
         if (this.tickNum % this.heartbeat != 0) {
           return;
         }
-        if (!this.isnotbtn && !this.media.isFinish && this.onPlay && !this.closeFace) {
-          console.log(this.isnotbtn , this.media.isFinish , this.onPlay, this.closeFace)
-          this.$message.errorMsg("需要安装摄像头才能学习", 2);
-          this.doPause()
-          return;
-        }
+        // if (!this.media.isFinish && this.onPlay && !this.closeFace) {
+        //   console.log(this.identifyFacePass , this.media.isFinish , this.onPlay, this.closeFace)
+        //   this.$message.errorMsg("需要安装摄像头才能学习", 2);
+        //   this.doPause()
+        //   return;
+        // }
         if (this.errCount >= this.maxErrorCount) {
           this.$message.errorMsg("人脸不在摄像头上", 5);
           this.destroyTimer()
@@ -412,9 +455,9 @@
         // 异常 10秒检查
         if (!this.closeFace) {
           if (this.errCount > 0) {
-            this.photograph()
+            this.photograph("video")
           } else if (heartBeat % this.collectBeat == 1) {
-            this.photograph()
+            this.photograph("video")
           }
         }
         // 主动暂停
@@ -545,4 +588,22 @@
     width: 80px;
     padding: -4px auto !important;
   }
+  .media-name {
+    width: 300px;
+    margin-left: 16px;
+    line-height: 24px;
+    white-space: nowrap;
+    overflow: hidden;
+    align-items: center;
+    text-overflow: ellipsis;
+  }
+  .media-process{
+    width: 8px;
+    height: 8px;
+    align-items: center;
+  }
+
+  .vjs-tech {
+    pointer-events: none;
+  }
 </style>

+ 2 - 3
src/containers/center/play/components/imedia.css

@@ -7,10 +7,9 @@
 }
 .m-chapter-list a {
   width: 100%;
-  height: 50px;
-  line-height: 50px;
+  height: 45px;
   border-bottom: 1px solid #f8f8f8;
-  font-size: 15px;
+  font-size: 16px;
   display: block;
   box-sizing: border-box;
   padding-left: 6px;

+ 8 - 8
src/containers/center/play/index.vue

@@ -157,8 +157,8 @@
         collectbeart: 20,
         closeFace: 0,
         options:{
-          controls:true,
-          autoplay: true, // 如果true,浏览器准备好时开始回放。
+          // controls:true,
+          autoplay: false, // 如果true,浏览器准备好时开始回放。
           muted: false, // 默认情况下将会消除任何音频。
           loop: false, // 导致视频一结束就重新开始。
           preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
@@ -168,12 +168,12 @@
           sources: [],
           poster: '', // 你的封面地址
           notSupportedMessage: '无法播放媒体源', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
-          controlBar: {
-            timeDivider: true,
-            durationDisplay: true,
-            remainingTimeDisplay: false,
-            fullscreenToggle: true
-          },
+          // controlBar: {
+          //   timeDivider: true,
+          //   durationDisplay: true,
+          //   remainingTimeDisplay: false,
+          //   fullscreenToggle: true
+          // },
           playtimes:""
         },
         list: [],

+ 1 - 1
src/main.js

@@ -20,7 +20,7 @@ require('es6-promise').polyfill()
 import './icons' // icon
 
 const hls = require('videojs-contrib-hls')
-require('video.js/dist/video-js.css')
+// require('video.js/dist/video-js.css')
 require('vue-video-player/src/custom-theme.css')
 
 Vue.use(hls)