移动端video转canvas总结

前言

公司一个客户要求我们参照http://game.flyh5.cn/resources/game/lq_game/2018_9_xmt_c/main.html?v=1557026481 做一个病毒式H5供宣传,打开一看就是那些场景应用的H5,主要流程就是一开始有几张照片,点不同照片播放不同视频,播放完视频上传图片生成海报。

我看了看他们的源码是使用白鹭egret+eui做的,动画效果还是不错的,本人才学疏浅(才疏学浅),做不到太炫酷的动画,加上项目比较赶,只给到两天时间,经过协商最终把一些复杂动画去掉了,主流程还是一样。

此项目纯前端,没用到后台接口

分析

项目要求点不同角色播放不同视频,我看了看他们的效果是没有那个视频工具栏,看了他们源码是把video转成canvas渲染上去,众所周知canvas是可以把画图像,canvas画视频应该就是把视频一帧一帧的画出来播放。

问题总结

先上最终部分代码

html


    

js(CSS的操作可以省略)

//视频转canvas
var canvasDrawVideo = {
  onLoad: function (canvas, url) {
    this.canvas = document.getElementById(canvas)
    this.video = document.getElementById('video')
    console.log(this.video.src)
    this.video.src = 'mlstatic/resource/vedio/' + url + '.mp4'
    this.ctx = this.canvas.getContext('2d')
    this.video.play()
    $('.div-draw').css({
      "z-index": "100"
    });
    $('#drawCanvas').fadeIn();
    var self = this;
    var timer;
    this.video.addEventListener("canplay", function () {
      // $("#loader").fadeOut();
      $('#video').css({
        "display": "block",
        "z-index": "998"
      });
      timer = window.setInterval(function () {
        // self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
        self.ctx.drawImage(self.video, 0, 0, self.canvas.width, self.canvas.height)
      }, 20);
    }, false);
    /* this.video.addEventListener('play', function () {
      
      $('#video').css({
        "display": "block",
        "z-index": "998"
      });
      timer = window.setInterval(function () {
        // self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
        self.ctx.drawImage(self.video, 0, 0, self.canvas.width, self.canvas.height)
      }, 20);
    }, false); */
    this.video.addEventListener('pause', function () {
      $('.div-draw').css({
        "z-index": "-1"
      });
      $('#drawCanvas').fadeOut();
      $('.uploadPic').css({
        "z-index": "10"
      });
      $('#video').css({
        "display": "none",
        "z-index": "0"
      });
      window.clearInterval(timer);
    }, false);
    this.video.addEventListener('ended', function () {
      $('.div-draw').css({
        "z-index": "-1"
      });
      $('#drawCanvas').fadeOut();
      $('.uploadPic').css({
        "z-index": "10"
      });
      $('#video').css({
        "display": "none",
        "z-index": "0"
      });
      clearInterval(timer);
    }, false);
    /* this.video.addEventListener("ended", function () {
      $('.div-draw').css({
        "z-index": "-1"
      });
      $('#drawCanvas').fadeOut();
      $('.uploadPic').css({
        "z-index": "10"
      });
    }) */
  },
  render: function () {
    function renderWord() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height)
      setTimeout(renderWord.bind(this), 60)
    }
    setTimeout(renderWord.bind(this), 60)
  },
}
canvasDrawVideo.onLoad('drawCanvas', vUrl)

坑1,客户提供的视频无法在H5播放,MP4会分批加载导致canvas渲染报错(iphone6P会播到一半刷新页面,提示遇到错误,重新加载)

首先排除代码问题,路径问题,浏览器不支持等问题。转码后的视频编码是mp4v,这是不能播放的原因,转换为AVC(H264)编码即可。

第一次我们转了H264还是有问题

后来选择移动设备兼容格式就好了,可以使用格式工厂转换移动端video转canvas总结_第1张图片

坑2,canvas视频不清晰问题

可以将画布 标签内的 width height调大

坑3,视频加载会卡

一开始是使用play监听视频播放开始画视频,后来改成‘canplay’,就是在视频准备好可以播放在开始渲染,不然视频缓存速度跟不上会造成卡顿,也可以使用canplaythrough,但是可能会等的时间比较长。最后还是选择canplay。

当浏览器能够开始播放指定的音频/视频时,发生 canplay 事件。

当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件。

移动端video转canvas总结_第2张图片

this.video.addEventListener('play', function () {
      timer = window.setInterval(function () {
        // self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
        self.ctx.drawImage(self.video, 0, 0, self.canvas.width, self.canvas.height)
      }, 20);
    }, false); 

坑4,iphone调用相机拍照会导致页面刷新,找遍网上,都说是内存不足导致的,最后发现确实是,因为一开始MP4的格式有问题,可以播放,但是可能会导致浏览器缓存,我们的视频都是十多兆的,所以在播放完视频调用相机内存可能会不够,后来把视频转成兼容移动端格式就没这个问题了,我想应该跟视频有一定关系。

下面补个微信上传照片的SDK(包括判断),不需传服务器,直接读取本地图片

//判断是否是ios
var isIos = checkIDE(/IPhone/i, "iphone");
//运行环境判断
function checkIDE(check, refer) {
  return String(window.navigator.userAgent.toLowerCase().match(check)) == refer;
}
//微信上传
function wechatUpload() {
  wx.chooseImage({
    count: 1, // 默认9
    sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
    sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
    success: function (res) {
      var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
      wx.getLocalImgData({
        localId: localIds[0], // 图片的localID
        success: function (res) {
          preview.src = res.localData; // localData是图片的base64数据,可以用img标签显示
          cut(res.localData);
        }
      });
    }
  });

}
$('.uploadBtn').on('click', function () {
  if (checkIDE(/MicroMessenger/i, "micromessenger") && isIos) {
    wechatUpload();
    return false
  }
})

项目还用到了裁剪,是腾讯QQ团队研发的兼容移动端的裁剪,这里就不赘述了,给大家个链接自行研究

https://alloyteam.github.io/AlloyCrop/

 

最后把项目最终微信链接给大家看看效果

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8b86b131a4101db1&redirect_uri=https%3A%2F%2Fwechat.qupiaowang.com%2Fact%2Findex.aspx%3Ft%3Dmalasong.html&response_type=code&scope=snsapi_userinfo&state=qupiaowang&connect_redirect=1#wechat_redirect

你可能感兴趣的:(jquery)