首页 > 其他分享 >web调用PC摄像头进行视频录制

web调用PC摄像头进行视频录制

时间:2023-05-11 21:22:52浏览次数:47  
标签:web mediaDevices thisVideo PC getUserMedia var navigator 摄像头

在项目中 我们很多时候都会遇到使用浏览器调用电脑设备的需求,记录一下实现思路及方法,共享一下技术点,同时也方便日后查看和整理

web浏览器在设计的时候为我们提供了很多的API接口实现功能,我们这次使用web调用PC摄像头和录音设备,主要思路是:获取到设备的媒体流,再将媒体流进行转存。

首先看一下目录结构

在components目录下定义一个提供视频录制功能的子组件,在Page目录下创建一个调用子组件的页面父组件。

接下来介绍一下子组件的功能方法:

调用摄像头 

先定义一个模板

<template>
  <div class="camera_outer">
    <video
      id="videoCamera"
      :width="videoWidth"
      :height="videoHeight"
      autoplay
    ></video>
    <!-- 放置图片 -->
    <canvas
      style="display: none"
      id="canvasCamera"
      :width="videoWidth"
      :height="videoHeight"
    ></canvas>
    <!-- 放置视频 -->
    <canvas
      style="display: none"
      id="canvasCameraTwo"
      :width="videoWidth"
      :height="videoHeight"
    ></canvas>
    <!-- <img src="/assets/logo.png" alt="" class="bg_r_img"> -->
    <div v-if="imgSrc" class="img_bg_camera" v-show="isShow">
      <img :src="imgSrc" alt="" class="tx_img" />
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      videoWidth: 540,
      videoHeight: 410,
      imgSrc: "",
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      thisCancasTwo: null,
      thisContextTwo: null,
      timer: null,
      isShow: true,
      mediaRecorder: null,
      recordedBlobs: [],
    };
  },
  computed: {},
  methods: {
    /*
     *@author
     *@function 绘制图片
     */
    setImage() {
      var _this = this;
      if (!_this.thisVideo) {
        alert("请先开启摄像头");
        return;
      }
      _this.isShow = true;
      //点击,canvas画图
      _this.thisContext.drawImage(
        _this.thisVideo,
        0,
        0,
        _this.videoWidth,
        _this.videoHeight
      );
      // 获取图片base64链接
      var image = this.thisCancas.toDataURL("image/png");
      //打印一下图片的base64码
      console.log("图片base64码:" + image);
      _this.imgSrc = image;
      this.$emit("refreshDataList", this.imgSrc);

      //将base64值传到后台
    },

    //加载本地摄像头
    changePhoto(){
      var that =this;
      /*得到所有的摄像头 */
      navigator.mediaDevices.enumerateDevices()
      .then(function(devices){
        console.log(devices);
        that.videoArr= [];
        devices.forEach((device) => {
          if (device.kind=='videoinput') {
            that.videoArr.push({
              'label':device.label,
              'id':device.deviceId
            })
            console.log('label:'+device.label+', id:'+device.deviceId);
          }
        });
        that.$emit('videoArr',that.videoArr);
      })
      .catch(function(err){
        console.log('ERROR:'+err.name+':'+err.message)
      })
    },
    //切换下拉
    changeSel(val){
      const videoConstraints={};
      if (val === '') {
        videoConstraints.facingMode = 'environment';
      }else{
        videoConstraints.deviceId = { exact: val };
      }
      var constraints ={
        video: videoConstraints,
      };
      //调用选中的摄像头
      this.getOneUserMedia(constraints);
    },
    //调用单个摄像头
    getOneUserMedia(constrains){
      var that =this;
      if (navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia(constrains).then(success=>{
          //开启摄像头
          that.thisVideo.srcObject=success;
          that.thisVideo.play();
        })
      }
    },
    //开启一个摄像头
    getOneCompetence() {
      var _this = this;
      this.thisCancas = document.getElementById("canvasCamera");
      this.thisContext = this.thisCancas.getContext("2d");
      this.thisVideo = document.getElementById("videoCamera");
      //设置视频放置数据
      this.thisCancasTwo = document.getElementById("canvasCameraTwo");
      this.thisContextTwo = this.thisCancasTwo.getContext("2d");

      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }

      // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
      // 使用getUserMedia,因为它会覆盖现有的属性
      // 这里,如果缺少getUserMedia属性,就添加它
      if (navigator.mediaDevices.getUserMedia == undefined) {
        navigator.mediaDevices.getUserMedia = function (constraints) {
          // 首先获取现存的getUserMedia(如果存在)
          var getUserMedia =
            navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia ||
            navigator.getUserMedia;
          // 有些浏览器不支持,会返回错误信息
          // 保持接口一致
          if (!getUserMedia) {
            return Promise.reject(
              new Error("getUserMedia is not implemented in this browser")
            );
          }
          //否则,使用promise将调用包装到旧的navigator.getUserMedia
          return new Promise(function (resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject);
          });
        };
      }
      //设置摄像头和麦克风是否启用
      var constraints = {
        audio: true,
        video: {
          width: this.videoWidth,
          height: this.videoHeight,
          transform: "scaleX(-1)",
          frameRate: 60,
        },
      };

      navigator.mediaDevices
        .getUserMedia(constraints)
        .then(function (stream) {
          window.stream = stream;
          //旧的浏览器可能没有srcObject
          if ("srcObject" in _this.thisVideo) {
            _this.thisVideo.srcObject = stream;
          } else {
            // 避免在新的浏览器中使用它,因为它正在被弃用。
            _this.thisVideo.src = window.URL.createObjectURL(stream);
          }
          //在视频的原数据加载后执行的方法
          _this.thisVideo.onloadedmetadata = function (e) {
            _this.thisVideo.play();
          };
        })
        .catch((err) => {
          console.log(err);
        });
    },

    /*
     *@author
     *@function 绘制视频
     */
    drawVideoAtCanvas() {
      var that=this;
      that.recordedBlobs = [];
      var options = { audioBitsPerSecond : 128000,videoBitsPerSecond : 100000,mimeType: 'video/webm;codecs=opus,vp8' };
      try {
        that.mediaRecorder = new MediaRecorder(window.stream, options);
      } catch (e) {
        return;
      }
      that.mediaRecorder.blobs = [];
      that.mediaRecorder.ondataavailable = function (e) {
        var blob = new Blob([e.data], { type: "video/mp4" });
        const blobUrl = window.URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.style.display = "none";
        a.download = "vvvvvv";
        a.href = blobUrl;
        a.click();
      };
      that.mediaRecorder.start();
    },
    //停止录制
    stopDrawVideoAtCanvas() {
      this.mediaRecorder.stop();
    },
    //关闭摄像头
    stopNavigator() {
      if (this.timer) {
        alert("请先停止录制~");
        return;
      }
      let tracks= this.thisVideo.srcObject.getTracks();
      tracks.forEach(track=>{
        track.stop();
      })
      this.isShow = false;
      this.thisVideo = null;
    },
  },
  mounted() {
    // this.getCompetence();
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    this.stopNavigator();
  },
};
</script>

 

我们通过MediaDevices接口访问连接媒体输入的设备。方法:

getOneCompetence()
通过getUserMedia()方法提示用户给我们摄像机的权限

我们通过MediaDevices接口访问连接媒体输入的设备

标签:web,mediaDevices,thisVideo,PC,getUserMedia,var,navigator,摄像头
From: https://www.cnblogs.com/Xiaomoml/p/14683782.html

相关文章

  • HTB ACADEMY-Web Fuzzing WRITE UP
    准备工作基本信息操作对象:VmwareStation(Kali-Linux)目标实例对象:178.128.46.49:30893/academy.htb安装单词列表(WordList),例如GithubSecLists,本次需要的单词列表文件如下:文件名用途/opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt......
  • 使用Open3D进行PCD拟合平面的Python代码示例
    使用Open3D进行PCD拟合平面的Python代码示例 importopen3daso3dimportnumpyasnp#读取点云数据pcd=o3d.io.read_point_cloud("2023042501.pcd")#创建PCD图pcd_graph=o3d.geometry.PointCloudGraph(pcd)#选择要拟合的平面plane_cent......
  • Spring MVC官方文档学习笔记(一)之Web入门
    注:该章节主要为原创内容,为后续的SpringMVC内容做一个先行铺垫1.Servlet的构建使用(1)选择Maven->webapp来构建一个web应用(2)构建好后,打开pom.xml文件,一要注意打包方式为war包,二导入servlet依赖,如下<!--打war包--><packaging>war</packaging><!--导入servlet依赖......
  • web游览器的标签页仿 ios mac 苹果的墓碑机制 (js代码)
    背景:本来项目开发系统防挂机功能,在其余游览器中均可以使用。但是呢在苹果的safair游览器中会出现几率失效,最后经过排查发现是苹果的墓碑机制导致。即:此标签页活跃,其他标签页假死。然后就导致防挂机失效了。原理:假如当前游览器中有3个标签页分别是A,B,C,每个标签页都有倒计时。正......
  • Qwik 1.0 发布,全栈式 Web 框架
    Qwik是一个全栈式Web框架,Qwik基于React、Angular和Vue等其他Web框架的概念,但以JavaScript流等更新的方法脱颖而出,允许以高性能向用户交付复杂的Web应用程序。随着Web应用程序变得越来越大,它们的启动性能会下降,因为当前的框架向客户端发送了太多的JavaScript......
  • c# 调用webapi的几种方式
     HttpHelper帮助类publicstaticclassHttphelper{//Post请求publicstaticstringPostResponse(stringurl,stringpostData,outstringstatusCode){stringresult=string.Empty;//设置Http的正文......
  • OData WebAPI实践-OData与EDM
    本文属于OData系列引言在OData中,EDM(EntityDataModel)代表“实体数据模型”,它是一种用于表示WebAPI中的结构化数据的格式。EDM定义了可以由OData服务公开的数据类型、实体和关系。EDM也提供了一些规则来描述数据模型中的实体之间的关系,例如继承、关联和复合类型。E......
  • JavaWeb之Servlet本质
    Servlet:服务器和Wepapp开发者之间的协议,sun公司已经规范了Servlet协议,Wepapp开发者只需要去实现规范接口类和对应的配置文件即可,Servlet底层是面向接口编程,用反射机制实例化一个类后再向下转型成Servlet类(因为Wepapp开发者实现规范好,只需到对应的文件中调用各个方法)菜鸟教程的解......
  • 拉普拉斯图像融合,基于sobel算子的边缘检测,PCA人脸识别,SIFT图像配准,分形维数计算,数字图
    拉普拉斯图像融合,基于sobel算子的边缘检测,PCA人脸识别,SIFT图像配准,分形维数计算,数字图像水印,霍夫变换做直线检测,人脸纹理识别,伪彩色增强,图像增强,图像分割,特征提取,字符分割,各种GUI,等等各种跟图像处理有关的程序。ID:1360615396171857......
  • brovery图像融合 IHS融合与PCA融合 PCNN图像融合 拉普拉斯图像融合
    brovery图像融合IHS融合与PCA融合PCNN图像融合拉普拉斯图像融合小波变换图像融合NSCT图像融合RGB加权图像融合ID:9750614972358887......