移动端视频播放的另一种方式

前几天做的一个移动端页面需要播放一段视频。嵌入页面video标签的方式肯定是不合适的。

因为页面需要的其实只是一个动画效果,对音频没有要求,所以就有机会选择其它的方式解决。最先想到的方案是 canvas-video,前不久 BM2 炫酷的微信广告就是用它实现的。原理很简单:

1
2
3
let context = canvas.getContext('2d');
// 在视频播放时,从video中取出图片,在画布上 drawImage
context.drawImage(video, 0, 0, width, height);

整个库除了做播放控制之外,还值得提的就是绘制时使用 requestAnimationFrame 优化,这儿就不多说了。效果实现之后,在自己手机 iOS 上看下效果,video 可以自动播放,虽然不能循环,效果还行。找了台安卓机测试发现,效果出不来,因为移动环境下的流量保护禁用自动播放。

然后在 github 上发现一个 canvid 项目用来解决移动端视频播放,它的方案是:将视频中的关键帧抽取出来,合并为一张图片,使用 canvas 播放图片。这个方案的浏览器支持肯定是没有问题的,问题是效果和加载速度如何。准备图片倒是折腾了一会,给的两个工具安装后直接使用报错,需要根据报错提示安装依赖的工具(两次)。之后的实现就很简单了,视频播放效果还很流畅。注意播放帧的设置,从源视频抽取图片时,是每 5 帧抽取一张图,这儿设置每秒 13 帧,与视频的每秒65帧是同步的。

现在的问题就是合并之后的图片太大了。canvid 有提醒:图片大小在一些移动端存在大小上限。后来把原图片分为 4 张图进行合并,每张大小在 700k 左右(无法再做压缩,ImageMagick 合并图片时已经做了压缩)。该库会在所有图片加载完成之后进行播放,在这儿我们可以进行一些简单的优化,在第一张图片加载完成之后就可以播放动画,播放时可以继续加载后面的图片。

为什么这种方式优于 gif 呢?
因为 gif 是无损压缩,jpg 是有损压缩,压缩比差距很大。

那如果我把图片有损压缩处理之后,再转成 gif 格式呢?
效果还是不如 jpg,因为 jpg 可以对这些图片的共同部分进行压缩。

当然最好还是使用视频格式,因为视频在播放的时候无需全部加载完成,而且在之后的数据传输可以传入差异数据。

最后,放下效果页面