vue前置拍照 录视频功能实现

在这里插入图片描述

HTML5官方文档解释:capture属性用于调用设备的摄像头或麦克风。(官方文档:www.w3.org/TR/2018/REC-html-media-capture-20180201/)

当accept=”audio/或video/”时capture只有两种值,一种是user,用于调用面向人脸的摄像头(例如手机前置摄像头),一种是environment,用于调用环境摄像头(例如手机后置摄像头)。
当accept=”audio”时,只要有capture就调用设备麦克风,忽略user和environment值。

iOS最遵守遵守HTML5规范,其次是X5内核,安卓的webview基本忽略了capture。 理想情况下应该按照如下开发webview:

  1. 当accept=”image/*”时,capture=”user”调用前置照相机,capture=”其他值”,调用后置照相机
  2. 当accept=”video/*”时,capture=”user”调用前置录像机,capture=”其他值”,调用后置录像机
  3. 当accept=”image/,video/”,capture=”user”调用前置摄像头,capture=”其他值”,调用后置摄像头,默认照相,可切换录像
  4. 当accept=”audio/*”时,capture=”放空或者任意值”,调用录音机
  5. 当input没有capture时,根据accppt类型给出文件夹选项以及摄像头或者录音机选项
  6. input含有multiple时访问文件夹可勾选多文件,调用系统摄像头或者录音机都只是单文件
  7. 无multiple时都只能单文件

capture (en-US) 属性是一个字符串,如果 accept (en-US) 属性指出了 input
是图片或者视频类型,则它指定了使用哪个摄像头去这些数据。值 user 表示应该使用前置摄像头和/或麦克风。值 environment
表示应该使用后置摄像头和/或麦克风。如果缺少此属性,则 user agent
可以自由决定做什么。如果请求的前置模式不可用,则用户代理可能退回到其首选的默认模式。

Note: capture 以前是一个布尔类型的属性,如果存在,则请求使用设备的媒体捕获设备(如:摄像机),而不是请求一个文件输入。

vue前置拍照:

<template>
  <div class="publish">
    <video ref="video"></video>
    <canvas style="display: none" id="canvasCamera"></canvas>
    <div v-if="imgSrc" class="img_bg_camera">
      <img :src="imgSrc" class="tx_img" />
    </div>
    <button @click="OpenCamera">打开摄像头</button>
    <button @click="CloseCamera">关闭摄像头</button>
    <button @click="setImage">拍照</button>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      mediaStreamTrack: {},
      video_stream: "", // 视频stream
      imgSrc: "", // 拍照图片
      canvas: null,
      context: null,
    };
  },
  mounted() {
    // 进入页面 自动调用摄像头
    this.getCamera();
  },
  methods: {
    // 调用打开摄像头功能
    getCamera() {
      // 获取 canvas 画布
      this.canvas = document.getElementById("canvasCamera");
      this.context = this.canvas.getContext("2d");
      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }
      // 正常支持版本
      navigator.mediaDevices
        .getUserMedia({
          video: true,
          audio: false,
        })
        .then((stream) => {
          // 摄像头开启成功
          this.mediaStreamTrack =
            typeof stream.stop === "function" ? stream : stream.getTracks()[0];
          this.video_stream = stream;
          this.$refs.video.srcObject = stream;
          this.$refs.video.play();
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 拍照 绘制图片
    setImage() {
      // 点击canvas画图
      this.context.drawImage(this.$refs.video, 0, 0, 200, 100);
      console.log("拍照", this.context.drawImage);
      // 获取图片base64链接 canvas
      this.canvas = document.getElementById("canvasCamera");
      this.canvas.style.display = "block";
      console.log(this.canvas, "拍照 image ", this.canvas.style);
      const image = this.cancas.toDataURL("image/png");
 
      this.imgSrc = image;
      console.log(this.imgSrc, "拍照 image ", image);
      //   this.$emit("refreshDataList", this.imgSrc);
    },
    // 打开摄像头
    OpenCamera() {
      console.log("打开摄像头");
      this.getCamera();
    },
    // 关闭摄像头
    CloseCamera() {
      console.log("关闭摄像头");
      this.$refs.video.srcObject.getTracks()[0].stop();
    },
  },
};
</script>
 
<style  scoped>
video {
  width: 100%;
  height: 300px;
}
canvas {
  width: 100%;
  height: 300px;
}
button {
  width: 100px;
  height: 40px;
  position: relative;
  bottom: 0;
  left: 0;
  background-color: rgb(22, 204, 195);
}
.img_bg_camera img {
  width: 300px;
  height: 200px;
}
</style>

h5拍照

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
  <title>摄像头拍照</title>
</head>
<body onload='init()'>
  <video id="video">
  </video>
  <div id='operators'>
    <button id="capture">拍照</button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button id="changeCamera">切换摄像头</button>
  </div>
  <canvas id="canvas" width="480" height="320"></canvas>
  <script>
 
	var cameraFront="";
    //访问用户媒体设备的兼容方法
    function getUserMedia(constraints, success, error) {
	  currentCamera=constraints;
      if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
      } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints,success, error)
      } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
      } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
      }
    }
 
    let video = document.getElementById('video');
    let canvas = document.getElementById('canvas');
    let context = canvas.getContext('2d');
    //视频流变量
	var localMediaStream;
 
    function success(stream) {
      //兼容webkit核心浏览器
      let CompatibleURL = window.URL || window.webkitURL;
      //将视频流设置为video元素的源
      console.log(stream);
      //video.src = CompatibleURL.createObjectURL(stream);
      video.srcObject = stream;
      video.play();
	   localMediaStream=stream;	
    }
 
    function error(error) {
      alert(`访问用户媒体设备失败${error.name}, ${error.message}`);
    }
 
    if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
      //调用用户媒体设备, 访问摄像头   video和audio:  {video : {width: 480, height: 320}}   使用前置摄像头, 代码如下: {video: {facingMode: 'user'}}    后置摄像头, 代码如下: {video: {facingMode: {exact : 'environment'}}}
      getUserMedia({audio: true,video: {facingMode: {exact : 'environment'}}}, success, error);
    } else {
      alert('不支持访问用户媒体');
    }
 
    document.getElementById('capture').addEventListener('click', function () {
      context.drawImage(video, 0, 0, 480, 320);      
    })
	//当前摄像头
	var currentCamera;
	document.getElementById('changeCamera').addEventListener('click', function () {
		//关闭打开的摄像头
		localMediaStream.getTracks().forEach(function(track) {
			track.stop();
		});
 
		if(currentCamera.video.facingMode=='user')
		{
			getUserMedia({audio: true,video: {facingMode: {exact : 'environment'}}}, success, error);
		}else{
			getUserMedia({audio: true,video: {facingMode: 'user'}}, success, error);
		}
    })
 
	function init(){
		document.getElementById('operators').style.width=document.getElementById('video').style.width;
		document.getElementById('operators').style.textAlign="center";
	}
  </script>
</body>
</html>

vue视频录制

在这里插入图片描述

<template>
  <div class="publish">
  	<!-- 下载按钮 -->
    <a id="downLoadLink" style="display: none;"></a>
    <video ref="video"></video>
    <!-- 视频录制或暂停 -->
    <div @click="recordOrStop">视频录制</div>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      mediaStreamTrack: {}, // 退出时关闭摄像头
      video_stream: '', // 视频stream
      recordedBlobs: [], // 视频音频 blobs
      isRecord: false, // 视频是否正在录制
    };
  },
  mounted() {
    // 进入页面 调用摄像头
    this.getCamera();
  },
  methods: {
    // 调用打开摄像头功能
    getCamera() {
      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }
      navigator.mediaDevices
        .getUserMedia({
          video: true,
        })
          .then((stream) => {
          // 摄像头开启成功
          this.mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
          this.video_stream = stream;
          this.$refs.video.srcObject = stream;
          this.$refs.video.play();
        })
        .catch(err => {
          console.log(err);
        });
    },
    // 录制或暂停
    recordOrStop() {
      if (this.isRecord) {
        this.stop();
      } else {
        this.record();
      }
    },
    // 视频录制
    record() {
      console.log('record');
      this.isRecord = !this.isRecord;
      let mediaRecorder;
      let options;
      this.recordedBlobs = [];
      if (typeof MediaRecorder.isTypeSupported === 'function') {
        // 根据浏览器来设置编码参数
        if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
          options = {
            MimeType: 'video/webm;codecs=h264',
          };
        } else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
          options = {
            MimeType: 'video/webm;codecs=h264',
          };
        } else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
          options = {
            MimeType: 'video/webm;codecs=vp8',
          };
        }
        mediaRecorder = new MediaRecorder(this.video_stream, options);
      } else {
        // console.log('isTypeSupported is not supported, using default codecs for browser');
        console.log('当前不支持isTypeSupported,使用浏览器的默认编解码器');
        mediaRecorder = new MediaRecorder(this.video_stream);
      }
      mediaRecorder.start();
      // 视频录制监听事件
      mediaRecorder.ondataavailable = e => {
        console.log(e);
        // 录制的视频数据有效
        if (e.data && e.data.size > 0) {
          this.recordedBlobs.push(e.data);
        }
      };
      // 停止录像后增加下载视频功能,将视频流转为mp4格式
      mediaRecorder.onstop = () => {
        const blob = new Blob(this.recordedBlobs, { type: 'video/mp4' });
        this.recordedBlobs = [];
        // 将视频链接转换完可以用于在浏览器上预览的本地视频
        const videoUrl = window.URL.createObjectURL(blob);
        // 设置下载链接
        document.getElementById('downLoadLink').href = videoUrl;
        // 设置下载mp4格式视频
        document.getElementById('downLoadLink').download = 'media.mp4';
        document.getElementById('downLoadLink').innerHTML = 'DownLoad video file';
        // 生成随机数字
        const rand = Math.floor((Math.random() * 1000000));
        // 生成视频名
        const name = `video${rand}.mp4`;
        
        // setAttribute() 方法添加指定的属性,并为其赋指定的值
        document.getElementById('downLoadLink').setAttribute('download', name);
        document.getElementById('downLoadLink').setAttribute('name', name);
		
		// 0.5s后自动下载视频
        setTimeout(() => {
          document.getElementById('downLoadLink').click();
        }, 500);
      };
    },
    // 停止录制
    stop() {
      this.isRecord = !this.isRecord;
      if (!this.$refs.video.srcObject) return;
      const stream = this.$refs.video.srcObject;
      const tracks = stream.getTracks();
      // 关闭摄像头和音频
      tracks.forEach(track => {
        track.stop();
      });
    },
  },
};
</script>
 
<style lang="less" scoped>
.publish {
  color: #fff;
  video {
    width: 100%;
    height: 100vh;
  }
  div {
    position: absolute;
    left: calc(50% - 80px);
    bottom: 0;
    height: 40px;
    width: 160px;
    font-size: 14px;
    border-radius: 10px;
    line-height: 40px;
    background-color: rgb(25, 179, 179);
    text-align: center;
  }
}
</style>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Vue 是一种前端 JavaScript 框架,它不支持直接拍照,因为它是在浏览器端运行的。但是,可以通过 HTML5 的 getUserMedia API 来访问用户的摄像头并实现拍照功能。 以下是一个简单的实现方法: 1. 在模板中添加一个 `<video>` 元素作为预览,并通过 ref 引用。 2. 在计算属性中,使用 `navigator.mediaDevices.getUserMedia` 访问用户的摄像头。 3. 将视频流作为 `srcObject` 绑定到预览元素上。 4. 在拍照按钮的点击事件处理程序中,使用 canvas 将预览图像绘制为图像,并将其作为图像数据 URL 保存。 示例代码: ``` <template> <div> <video ref="video" /> <button @click="takePicture">Take Picture</button> <img v-if="pictureDataURL" :src="pictureDataURL" /> </div> </template> <script> export default { data() { return { pictureDataURL: null }; }, computed: { stream() { return this.$refs.video.srcObject; } }, mounted() { navigator.mediaDevices .getUserMedia({ video: true }) .then(stream => { this.$refs.video.srcObject = stream; }); }, methods: { takePicture() { const canvas = document.createElement("canvas"); canvas.width = this.$refs.video.videoWidth; canvas.height = this.$refs.video.videoHeight; canvas .getContext("2d") .drawImage(this.$refs.video, 0, 0, canvas.width, canvas.height); this.pictureDataURL = canvas.toDataURL(); } } }; </script> ``` 注意:在不同的浏览器中,访问 ### 回答2: 使用Vue实现拍照功能可以分为以下几个步骤: 1. 首先,我们需要在Vue组件中引入相关的依赖包,例如vue-web-cam、@vue/reactivity等。 2. 在组件的data属性中定义一个变量,用于保存拍照后的图片数据。 3. 在组件的template模板中,使用vue-web-cam组件来渲染摄像头视频流,并设置相应的参数,例如摄像头的ID、宽度、高度等。 4. 在template中添加一个拍照按钮,通过v-on:click指令,绑定一个方法来处理拍照事件。 5. 在组件的methods属性中定义该方法,方法中可以通过调用vue-web-cam组件提供的`capture()`方法来实现拍照功能,并将拍照后的图片数据保存到之前定义的变量中。 6. 最后,在template中展示拍照后的图片数据,可以使用`v-if`指令来判断是否有拍照的图片数据,然后通过`<img>`标签来展示图片。 需要注意的是,在实际开发过程中,还需要关注一些细节,例如在调用摄像头前需要用户授权;对于一些老旧的浏览器,可能需要使用特定的polyfill来提供摄像头功能支持等。 总结起来,通过使用Vue以及相关依赖包,我们可以轻松地实现拍照功能,通过调用摄像头接口和拍照按钮来操作摄像头,并将拍照后的图片数据保存下来并展示在页面中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值