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


Posted in Javascript onJuly 27, 2018

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

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

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

Javascript 相关文章推荐
收集的一些Array及String原型对象的扩展实现代码
Dec 05 Javascript
利用jQuery实现漂亮的圆形进度条倒计时插件
Sep 30 Javascript
Javascript函数式编程语言
Oct 11 Javascript
Django1.7+JQuery+Ajax验证用户注册集成小例子
Apr 08 jQuery
vue快捷键与基础指令详解
Jun 01 Javascript
详解react-router4 异步加载路由两种方法
Sep 12 Javascript
JS设计模式之状态模式概念与用法分析
Feb 05 Javascript
JavaScript设计模式之代理模式简单实例教程
Jul 03 Javascript
在vue中安装使用vux的教程详解
Sep 16 Javascript
vue项目引入字体.ttf的方法
Sep 28 Javascript
jquery图片预览插件实现方法详解
Jul 18 jQuery
vue 计算属性和侦听器的使用小结
Jan 25 Vue.js
JavaScript事件对象event用法分析
Jul 27 #Javascript
详解vue.js下引入百度地图jsApi的两种方法
Jul 27 #Javascript
JavaScript中为事件指定处理程序的五种方式分析
Jul 27 #Javascript
浅谈Redux中间件的实践
Jul 27 #Javascript
JavaScript多态与封装实例分析
Jul 27 #Javascript
Vue配合iView实现省市二级联动的示例代码
Jul 27 #Javascript
react native 文字轮播的实现示例
Jul 27 #Javascript
You might like
PHP 可阅读随机字符串代码
2010/05/26 PHP
php ajax 静态分页过程形式
2011/09/02 PHP
php中json_encode处理gbk与gb2312中文乱码问题的解决方法
2014/07/10 PHP
php中常见的sql攻击正则表达式汇总
2014/11/06 PHP
PHP实现HTML页面静态化的方法
2015/11/04 PHP
jQuery Ajax之load()方法
2009/10/12 Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
2013/04/19 Javascript
jquery仿搜索自动联想功能代码
2014/05/23 Javascript
javascript实现带节日和农历的日历特效
2015/02/01 Javascript
js实现右下角提示框的方法
2015/02/03 Javascript
javascript实现的网站访问量统计代码
2015/12/20 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
node.js express安装及示例网站搭建方法(分享)
2016/08/22 Javascript
AngularJS 过滤与排序详解及实例代码
2016/09/14 Javascript
jquery遍历标签中自定义的属性方法
2016/09/17 Javascript
简单谈谈CommonsChunkPlugin抽取公共模块
2017/12/31 Javascript
小程序ios音频播放没声音问题的解决
2018/07/11 Javascript
iview在vue-cli3如何按需加载的方法
2018/10/31 Javascript
Javascript读写cookie的实例源码
2019/03/16 Javascript
在vue项目中使用sass语法问题
2019/07/18 Javascript
Windows下为Python安装Matplotlib模块
2015/11/06 Python
利用Python画ROC曲线和AUC值计算
2016/09/19 Python
Python实现MySQL操作的方法小结【安装,连接,增删改查等】
2017/07/12 Python
python检测IP地址变化并触发事件
2018/12/26 Python
python实现文件的分割与合并
2019/08/29 Python
详解CSS3实现响应式手风琴效果
2020/06/10 HTML / CSS
佐卡伊官网:中国知名珠宝品牌
2017/02/05 全球购物
Hotels.com韩国:海外国内旅行所需的酒店和住宿预订网站
2020/05/08 全球购物
您熟悉ORM(Object-Relation Mapping)吗?请谈谈您所理解的ORM
2016/02/08 面试题
DataList 能否分页,请问如何实现?
2015/05/03 面试题
医学院学生求职简历的自我评价
2013/10/24 职场文书
事业单位公务员的职业生涯规划
2014/01/15 职场文书
法学专业毕业生自荐信
2014/06/11 职场文书
房产公证书格式
2015/01/26 职场文书
入党培养人考察意见
2015/06/08 职场文书
我的中国梦心得体会范文
2016/01/05 职场文书