vue 录制视频并压缩视频文件的方法
文件上传框<input type="file">,除了可以选择文件上传之外,还可以调用摄像头来拍摄照片或者视频并上传。capture属性可以判断前置or后置摄像头。在视频播放的过程中,用canvas定时截取一张图片,然后用生成一张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>
试过很多种方法,而这种在移动端浏览器(特别是微信浏览器!)的兼容性是最好的。但是这个生成的视频文件将会失去音频,如果需要音频的可以看我另一篇简书有说明几种方法。有更好的方法欢迎大家留言,互相学习~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。