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 相关文章推荐
你的编程语言可以这样做吗?
Sep 07 Javascript
jquery 获取标签名(tagName)示例代码
Jul 11 Javascript
使用jquery修改表单的提交地址基本思路
Jun 04 Javascript
JavaScript中常用的六种互动方法示例
Mar 13 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
Nov 25 Javascript
前端框架Vue.js中Directive知识详解
Sep 12 Javascript
js判断文件格式及大小的简单实例(必看)
Oct 11 Javascript
AngularJS实现使用路由切换视图的方法
Jan 24 Javascript
AngularJS 的$timeout服务示例代码
Sep 21 Javascript
vue mint-ui tabbar变组件使用
May 04 Javascript
微信小程序用户位置权限的获取方法(拒绝后提醒)
Nov 15 Javascript
小程序的上传文件接口的注意要点解析
Sep 17 Javascript
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 array_map array_multisort 高效处理多维数组排序
2009/06/11 PHP
php curl选项列表(超详细)
2013/07/01 PHP
php中heredoc与nowdoc介绍
2014/12/25 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.2 0
2008/03/22 Javascript
自制轻量级仿jQuery.boxy对话框插件代码
2010/10/26 Javascript
JQuery中如何传递参数如click(),change()等具体实现
2013/04/28 Javascript
jquery ajax实现下拉框三级无刷新联动,且保存保持选中值状态
2013/10/29 Javascript
图解Sublime Text3使用技巧
2015/12/21 Javascript
jquery拖拽效果完整实例(附demo源码下载)
2016/01/14 Javascript
懒加载实现的分页&amp;&amp;网站footer自适应
2016/12/21 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
用vue的双向绑定简单实现一个todo-list的示例代码
2017/08/03 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
SVG实现时钟效果
2018/07/17 Javascript
解决Layui数据表格中checkbox位置不居中的方法
2018/08/15 Javascript
Python编程之string相关操作实例详解
2017/07/22 Python
Python通过matplotlib绘制动画简单实例
2017/12/13 Python
Python异常对代码运行性能的影响实例解析
2018/02/08 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
详解python中init方法和随机数方法
2019/03/13 Python
python支持多线程的爬虫实例
2019/12/21 Python
PyCharm 无法 import pandas 程序卡住的解决方式
2020/03/09 Python
Python 打印自己设计的字体的实例讲解
2021/01/04 Python
python爬虫实现爬取同一个网站的多页数据的实例讲解
2021/01/18 Python
台湾前三大B2C购物网站:MOMO购物网
2017/04/27 全球购物
高二历史教学反思
2014/01/25 职场文书
项目经理任命书
2014/06/04 职场文书
通报表扬范文
2015/01/17 职场文书
法制工作总结2015
2015/07/23 职场文书
2017大学生寒假社会实践心得体会
2016/01/14 职场文书
Java 在生活中的 10 大应用
2021/11/02 Java/Android
Java 在线考试云平台的实现
2021/11/23 Java/Android
java中如何截取字符串最后一位
2022/07/07 Java/Android
win10壁纸在哪个文件夹 win10桌面背景图片文件位置分享
2022/08/05 数码科技