使用getUserMedia实现录像

5 篇文章 0 订阅

兼容性:

自测如下:在这里插入图片描述

template代码

页面交互根据需求定义
此处为主要功能代码,全部代码需私信

 <mt-button class="next_submit" type="default" @click.native="camera" v-if="nextSign">开始人脸识别</mt-button>
 <video class="video_rolate" 
          width="255px"
          height="255px"
          :src="url" ref="videoRef" 
          x-webkit-airplay="true" 
          x5-video-player-fullscreen="true" 
          x5-video-orientation="h5" 
          playsinline="true" 
          autoplay 
          x5-video-player-type="h5" 
          webkit-playsinline="true"></video>

//播放录制的视频流
<video ref="videob" controls=""  name="media"  width="100%" height="400"></video>

js代码

data(){
return {
      showVideo: false,
      mediaRecorder: null,
      MediaStreamTrack: null,
      isAlreadyRecord: false,
      count: 3,//录制时间 s
      startTime:3000,//和count保持一致
      countTimer: null,
      counts:3,//待开始录制时长 s
      recordedBlobs: [],//视频流
      randomColor:"#eee",//变色颜色
      border:'#fff',//边框颜色
      isUpload:false,//上传中状态
      faceResult:false
}}
// 调用摄像头 开始录制
      async camera () {
        //在每次执行前,先关闭设备。
        if (window.stream) {
          window.stream.getTracks().forEach(track => {
                track.stop();
            });
        }  
        let constraints = {
          audio: false,
          video: {
            facingMode:{ exact: "user" } // 调前置摄像头
            // frameRate: { ideal: 10, max: 15 } //控制视频帧率
          }
        }
        // 旧版本浏览器不支持navigator.mediaDevices,设置一个空的对象
        if (navigator.mediaDevices === undefined) {
          navigator.mediaDevices = {};
        }
        // 部分浏览器部分支持 navigator.mediaDevices,在没有getUserMedia属性的时候添加它。
        if (navigator.mediaDevices.getUserMedia === undefined) {
          navigator.mediaDevices.getUserMedia = function (constraints) {
            // 首先,如果有getUserMedia的话,就获得它
            var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
            // 部分浏览器不支持- 返回一个error到promise的reject来保持一个统一的接口
            if (!getUserMedia) {
              this.mediaList=true;
              $.showConfirm(
                '该浏览器不支持,请使用其他浏览器',
                "",
                "好的",
                "",
                () => {
                  // router.replace({ name: 'home' });
              },false);
              return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }
            // 否则,为老的navigator.getUserMedia方法包裹一个Promise
            return new Promise(function (resolve, reject) {
              getUserMedia.call(navigator, constraints, resolve, reject);
            })
          }
        }
        // this.getSystem();
        this.mediaList = false;
        let times=null;  
        const delay= (time = 0) => new Promise((res) => { setTimeout(res, time)});
        const tapStream = await navigator.mediaDevices.getUserMedia(constraints);
        let MediaStreamTracks = typeof tapStream.stop === 'function' ? tapStream : tapStream.getVideoTracks()[0];
        if(this.isWeChart() && /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
          //ios微信端第一次getUserMedia的stream不能播放
          await delay(1000); // 第一次需延迟关闭摄像头
          MediaStreamTracks && MediaStreamTracks.stop();
          await delay(100);
        }
        navigator.mediaDevices.getUserMedia(constraints)
          .then(async (stream) => {
            this.MediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getVideoTracks()[0];
            // 显示录制框
            // this.mediaList = false;
            this.showVideo = true;
            this.isAlreadyRecord = false;
            let isUrl = window.URL|| window.webkitURL|| window.mozURL|| window.msURL;
           
            if ('srcObject' in this.$refs.videoRef) {
              this.$refs.videoRef.srcObject = stream;    
            } else {              
              this.$refs.videoRef.src = isUrl.createObjectURL(stream);
            }
            if(this.isWeChart() && /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
              this.$refs.videoRef.play(); 
            }
            //录像容器
            this.$refs.videoRef.onloadedmetadata = e => {
                // 播放视频
                this.$refs.videoRef.play(); 
            }
            let options = {
              videoBitsPerSecond: 2500000,
              // mimeType:'video/webm;codecs=h264'
            }
            this.mediaRecorder = new MediaRecorder(stream, options);
            clearInterval(times);
            this.counts=3;
            times=setInterval(()=>{
              this.counts--;
              if(this.counts==1){
                clearInterval(times);
                this.saveRecord();
              }
            },1000);
          })
          .catch((err) => {
            this.goStart();
           
            if(err.message == 'Permission denied'){
              $.showConfirm(
                '摄像头开启失败,请检查摄像头是否授权或是否可用!',
                "",
                "好的",
                "",
                () => {
                  // router.replace({ name: 'home' });
              },false);
             
            }else{
              $.showConfirm(
              '摄像头开启失败,请使用其他浏览器!',
              "",
              "好的",
              "",
              () => {
                // router.replace({ name: 'home' });
              },false);
            }
          })
      },
      // 录制倒计时
      recordcountDown() {
        let timess=null,sjTime=null;
        //三秒后自动结束
        clearInterval(timess);
        clearInterval(sjTime);
        sjTime=setInterval(()=>{
          this.getsjColor();
        },300)
        timess=setInterval(()=>{
            this.count--;
            if(this.count<1){
              clearInterval(timess);
              clearInterval(sjTime);
              this.randomColor='#fff';
              this.saveRecord();
            }
          },1000)
      },
      // 保存录制视频
      saveRecord() {
        if (this.isAlreadyRecord) {
          this.recordedBlobs=[];
          clearTimeout(this.countTimer);
          // this.showVideo=false;
          this.isUpload=true;
          //当录制的数据可用时
          this.mediaRecorder.ondataavailable = (e) => {
            console.log(e.data)
            if (e.data && e.data.size > 0) {
              this.recordedBlobs.push(e.data);
            }
          }
          this.mediaRecorder.stop();
          setTimeout(() => {
            var blob = new Blob(this.recordedBlobs, {type: 'video/mp4'});
            //blob转file
            var file = new File([blob], Date.now(), {type: 'video/mp4', lastModified: Date.now()});
           
            this.isAlreadyRecord = false;
            this.MediaStreamTrack && this.MediaStreamTrack.stop();
            var reader = new FileReader();
            reader.readAsDataURL(blob, 'utf-8');
            reader.onload = () => {
              // console.log(reader.result); // base64格式
              setTimeout(()=>{
                this.faceResult=true;
              },2000)
              //录制并上传后端
              this.$refs.videob.src = reader.result;
            }
          }, 1000);
        } else {
          this.count = 3;
          this.isAlreadyRecord = true;
          this.mediaRecorder.start(3000);
          this.recordcountDown();
        }
      },
      //重新录制
      again(){
        this.MediaStreamTrack && this.MediaStreamTrack.stop();
        this.countTimer && clearTimeout(this.countTimer);
        this.mediaList=true;
        this.faceResult=false;
        this.showVideo=false;
        this.isUpload=false;
      },
      isWeChart(){
        var userAgent = navigator.userAgent.toLowerCase();
        let isW=false;
        if(userAgent.match(/MicroMessenger/i) == 'micromessenger' || userAgent.match(/_SQ_/i) == '_sq_'){
          isW= true;
        }else{
          isW= false;
        }
        return isW;
      }
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值