首页 > 编程 > JavaScript > 正文

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

2019-11-19 13:24:15
字体:
来源:转载
供稿:网友

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

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

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

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>

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

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表