欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue 录制视频并压缩视频文件的方法

程序员文章站 2022-04-10 15:30:38
文件上传框,除了可以选择文件上传之外,还可以调用摄像头来拍摄照片或者视频并上传。capture属性可以判断前置or后置摄像...

文件上传框<input type="file">,除了可以选择文件上传之外,还可以调用摄像头来拍摄照片或者视频并上传。capture属性可以判断前置or后置摄像头。在视频播放的过程中,用canvas定时截取一张图片,然后用生成一张gif图,从而完成前端的视频压缩。

我这里使用的是vue写的,以下是我的流程及代码:

一、下载gif.js相关文件,,然后将这几个文件放在根目录的static/js里面。

vue 录制视频并压缩视频文件的方法

gif.js相关文件及存放路径

二、下载依赖包:

npm i timers

三、在页面中声明:

import { setinterval, clearinterval } from "timers";
import gif from "../../static/js/gif.js"

四、html代码块:

<template>
 <div>
   <input ref="changeinput" type="file" accept="video/*" capture="user" @change="changevideo" />
   <div>
    <div>视频大小:{{videosize}}</div>
    <div>视频时长:{{videolength}}</div>
    <div>
     <video id="myvideo" :src="videosrc" :width="winwidth" :height="winheight" ref="videoid" autoplay="true" controls muted></video>
     <canvas id="canvas" :width="winwidth" :height="winheight"></canvas>
    </div>
   </div>
 </div>
</template>

五、在页面加载完成时初始化gif:

mounted(){
  //初始gif
  this.gif = new gif({
   workers: 1,
   quality: 1000,
   width: window.innerwidth,
   height: window.innerheight,
   workerscript: '../../static/js/gif.worker.js',
  });
 },

六、当input录制完视频返回页面中,获取到这个视频文件,每次拿到视频文件需要先移除之前的监听:

//input文件走向
  changevideo(e){
   var file = e.target.files[0];
   const video = document.getelementbyid('myvideo');
   //视频开始播放
   video.removeeventlistener('play', this.videoplay, false);
   //视频播放完
   video.removeeventlistener('ended', this.videoended, false); 
   this.androidfile(file);
  },

七、上一步提到的this.androidfile方法,是通过这个视频文件,在页面播放一遍,在这个播放过程处理视频,完成整个转换过程,获取到最终的文件:

//安卓拍摄视频
  androidfile(file){
   //视频字节大小
   this.videosize = file.size;

   const that = this;
   const video = document.getelementbyid('myvideo');
   const canvas = document.getelementbyid('canvas');
   var context = canvas.getcontext('2d');

   this.gifsettime = true;
   this.gif.abort()
   this.gif.frames = [];

   //file转base64
   var reader = new filereader();
   reader.readasdataurl(file);
   reader.onload = function () {
    that.videosrc = this.result;
    video.play();
   }
   //视频开始播放
   video.addeventlistener('play', this.videoplay, false);
   //视频播放完
   video.addeventlistener('ended', this.videoended, false); 
   //获取到所有的图片并渲染完后执行
   this.gif.on('finished', function(blob) {
    if(that.fileandroid.size == blob.size) return;
    console.log("gif的blob文件",blob);
    //file
    that.fileandroid = that.convertbase64urltofile(blob);
    //上传视频文件
    that.uploadvideo(that.fileandroid);
   });
  },

八、步骤七所说的this.videoplay方法。视频在页面播放过程中,每200毫秒通过canvas截取一张图片,把这些图片一张张给gif.js堆叠:

//视频开始播放
  videoplay(){
   const that = this;
   const video = document.getelementbyid('myvideo');
   const canvas = document.getelementbyid('canvas');
   var context = canvas.getcontext('2d');
   console.log("视频时长",video.duration);
   this.videolength = video.duration;
    //画布上画视频,需要动态地获取它,一帧一帧地画出来
    var times = setinterval(function(){
      context.drawimage(video, 0, 0, that.winwidth, that.winheight);
      that.gif.addframe(context, {
       copy: true
      });
      if(that.gifsettime == false){
       clearinterval(times);
      }
    }, 200);
  },

九、步骤七所说的this.videoended方法。视频播放完,通过gif.js将图片堆叠的动态图渲染出来:

//视频播放完
  videoended(){
   this.gifsettime = false;
   console.log("视频播放完毕!")
   this.gif.render();
  },

十、步骤七所说的that.convertbase64urltofile方法。将gif.js生成的blob文件转换成file格式:

//blob to file
  convertbase64urltofile(blob) {
   var d = new date().gettime();
   var type = 'image/gif'
   return new file([blob],"filegif-" + d + '.gif', {type:type});
  },

最后通过步骤七所说的that.uploadvideo方法,上传图片给服务器:

//上传视频
  uploadvideo(file){
   console.log("上传的视频文件", file)
  },

在这提供我的全部代码,android的视频文件比较大所以做压缩,而ios本身存在视频压缩,所以我这里做了区分

<template>
 <div>
   <input ref="changeinput" type="file" accept="video/*" capture="user" @change="changevideo" />
   <div>
    <div>视频大小:{{videosize}}</div>
    <div>视频时长:{{videolength}}</div>
    <div>
     <video id="myvideo" :src="videosrc" :width="winwidth" :height="winheight" ref="videoid" autoplay="true" controls muted></video>
     <canvas id="canvas" :width="winwidth" :height="winheight"></canvas>
    </div>
   </div>
 </div>
</template>

<script>
import { setinterval, clearinterval } from "timers";
import gif from "../../static/js/gif.js"
export default {
 data(){
  return {
   videosize: '',
   videosrc: '',
   videolength: '',
   isandroid: false,
   fileandroid: {},
   winwidth: window.innerwidth,
   winheight: window.innerheight,
   gifsettime: false,
   gif: '',
  }
 },
 created() {
  //判断终端
  var u = navigator.useragent;
  var isandroid = u.indexof('android') > -1 || u.indexof('adr') > -1; //android终端
  var isios = !!u.match(/\(i[^;]+;( u;)? cpu.+mac os x/); //ios终端
  if(isandroid){
   console.log('isandroid')
   this.isandroid = true;
  }else if(isios){
   console.log('isios')
   this.isandroid = false;
  }
 },
 mounted(){
  //初始gif
  this.gif = new gif({
   workers: 1,
   quality: 1000,
   width: this.winwidth,
   height:this.winheight,
   workerscript: '../../static/js/gif.worker.js',
  });
 },
 methods:{
  //input文件走向
  changevideo(e){
   var file = e.target.files[0];
   const video = document.getelementbyid('myvideo');
   
   if(file !== undefined){
    //判断走向
    if(this.isandroid){
     //视频开始播放
     video.removeeventlistener('play', this.videoplay, false);
     //视频播放完
     video.removeeventlistener('ended', this.videoended, false); 
     this.androidfile(file);
    }else{
     this.iphonefile(file);
    }
   }
  },
  //ios拍摄视频
  iphonefile(file){
   const that = this;
   //视频字节大小
   this.videosize = file.size;
   
   var url = null ; 
   //file转换成blob
   if (window.createobjecturl!=undefined) { // basic
    url = window.createobjecturl(file) ;
   } else if (window.url!=undefined) { // mozilla(firefox)
    url = window.url.createobjecturl(file) ;
   } else if (window.webkiturl!=undefined) { // webkit or chrome
    url = window.webkiturl.createobjecturl(file) ;
   }
   this.videosrc = url;
   if(file.size < 2100000 && file.size > 500000){
    this.uploadvideo(file);
   }else if(file.size >= 2100000){
    this.$vux.toast.text('视频太大,请限制在10秒内');
   }else{
    this.$vux.toast.text('视频录制不能少于5秒');
   }
  },
  //安卓拍摄视频
  androidfile(file){
   //视频字节大小
   this.videosize = file.size;

   const that = this;
   const video = document.getelementbyid('myvideo');
   const canvas = document.getelementbyid('canvas');
   var context = canvas.getcontext('2d');

   this.gifsettime = true;
   this.gif.abort()
   this.gif.frames = [];

   //file转base64
   var reader = new filereader();
   reader.readasdataurl(file);
   reader.onload = function () {
    that.videosrc = this.result;
    video.play();
   }
   //视频开始播放
   video.addeventlistener('play', this.videoplay, false);
   //视频播放完
   video.addeventlistener('ended', this.videoended, false); 
   
   this.gif.on('finished', function(blob) {
    if(that.fileandroid.size == blob.size) return;
    console.log("gif的blob文件",blob);
    that.fileandroid = that.convertbase64urltofile(blob);
    that.uploadvideo(that.fileandroid);
   });
  },
  //视频开始播放
  videoplay(){
   const that = this;
   const video = document.getelementbyid('myvideo');
   const canvas = document.getelementbyid('canvas');
   var context = canvas.getcontext('2d');
   console.log("视频时长",video.duration);
   this.videolength = video.duration;
    //画布上画视频,需要动态地获取它,一帧一帧地画出来
    var times = setinterval(function(){
      context.drawimage(video, 0, 0, that.winwidth, that.winheight);
      that.gif.addframe(context, {
       copy: true
      });
      if(that.gifsettime == false){
       clearinterval(times);
      }
    }, 200);
  },
  //视频播放完
  videoended(){
   this.gifsettime = false;
   console.log("视频播放完毕!")
   this.gif.render();
  },
  //blob to file
  convertbase64urltofile(blob) {
   var d = new date().gettime();
   var type = 'image/gif'
   return new file([blob],"filegif-" + d + '.gif', {type:type});
  },
  //上传视频
  uploadvideo(file){
   console.log("上传的视频文件", file)
  },
 }
};
</script>
<style scoped>

</style>

试过很多种方法,而这种在移动端浏览器(特别是微信浏览器!)的兼容性是最好的。但是这个生成的视频文件将会失去音频,如果需要音频的可以看我另一篇简书有说明几种方法。有更好的方法欢迎大家留言,互相学习~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。