安卓和IOS对于html5中的video兼容一直是大问题,各类不同,体验还不好。这段时间作一个html的video播放的时候,要求全屏展现,真是各类问题。下面就就记一下这个项目中遇到的一下手机兼容问题和对应的处理方法。查资料的过程当中,发现针对于video的兼容问题仍是比较多个,会罗列视频播放的通用场景和各个场景下踩过的坑,但愿在需求开发的时候,可以针对合适的场景,选择合适的技术方案。有相关的补充,欢迎你们进行补充。php
src
视频的地址poster
容许用户控制视频的播放,包括音量,跨帧,暂停/恢复播放。controls
属性规定视频下载时显示的图像,或者在用户点击播放按钮前显示的图像preload
在页面加载后载入视频webkit-playsinline
&& playsinline
视频播放时局域播放,不脱离文档流 。可是这个属性比较特别, 须要嵌入网页的APP好比WeChat中UIwebview 的allowsInlineMediaPlayback = YES webview.allowsInlineMediaPlayback = YES,才能生效。换句话说,若是APP不设置,你页面中加了这标签也无效,这也就是为何安卓手机WeChat 播放视频老是全屏,由于APP不支持playsinline,而ISO的WeChat却支持。x-webkit-airplay
这个属性应该是使此视频支持ios的AirPlay功能。使用AirPlay能够直接从使用iOS的设备上的不一样位置播放视频、音乐还有照片文件,也就是说经过AirPlay功能能够实现影音文件的无线播放,固然前提是播放的终端设备也要支持相应的功能x5-video-player-type
启用同层H5播放器,就是在视频全屏的时候,div能够呈如今视频层上,也是WeChat安卓版特有的属性。同层播放别名也叫作沉浸式播放,播放的时候看似全屏,可是已经除去了control和微信的导航栏,只留下"X"和"<"两键。目前的同层播放器只在Android(包括微信)上生效,暂时不支持iOS。至于为何同层播放只对安卓开放,是由于安卓不能像ISO同样局域播放,默认的全屏会使得一些界面操做被阻拦,若是是全屏H5还好,可是作直播的话,诸如弹幕那样的功能就没法实现了,因此这时候同层播放的概念就解决了这个问题。不过在测试的过程当中发现,不一样版本的IOS和安卓效果略有不一样 安卓效果图-如图所示x5-video-orientation
声明播放器支持的方向,可选值landscape 横屏, portraint竖屏。默认值portraint。不管是直播仍是全屏H5通常都是竖屏播放,可是这个属性须要x5-video-player-type开启H5模式x5-video-player-fullscreen
全屏设置。它又两个属性值,ture和false,true支持全屏播放,false不支持全屏播放。其实,IOS 微信浏览器是Chrome的内核,相关的属性都支持,也是为何X5同层播放不支持的缘由。安卓微信浏览器是X5内核,一些属性标签好比playsinline就不支持,因此始终全屏。早期的安卓和IOS都须要用户手势才能自动播放,后期逐渐放宽的自动播放的策略,逐渐开始支持自动播放,固然在不一样的安卓微信手机和对应的浏览器上,展现略有差别,这个没有彻底清楚因此机型展现状况。css
PC端的浏览器具体状况有所差异,这个没有进行深刻研究,你们有采坑欢迎进行补充。html
真正的作法是,检测当前的浏览器是否能支持自动播放,示例代码:前端
var promise = document.querySelector('video').play(); if (promise !== undefined) { promise.then(() => { // video can play }).catch(err => { // video cannot play }) }
document.addEventListener('WeixinJSBridgeReady', function () { music.play() }, false)
这个其实并不难,安卓和IOS,在微信环境下打开,默认应该都是全屏(不是视频占据整个手机的全屏,而是占用body内的视窗范围以内)html5
安卓全屏效果,没有顶部的导航栏,只有”>“ 和 ”...“,[效果以下]:android
IOS会直接打开全屏模式。效果以下:ios
IOS的非全屏展现。对安卓无影响 IOS效果图-如图所示:es6
可是有的时候不想全屏展现,只须要加上webkit-playsinline
&& playsinline
便可,视频播放不脱离文档流,进行局部播放。安卓状况下有'...', 若是安装过QQ浏览器会能进行小窗播放,悬浮在页面的最上面,这个现象符合条件都有,可是不能去掉。这个仍是解决不了的,不过通常这样操做的用户仍是在少数。web
video 元素有提供多个行为事件供开发者控制视频播放,兼容性比较好的有 onended 、 ontimeupdate、onplay、onplaying等,有些事件在不一样浏览器不一样设备上的的表现状况并不一致,不一样的系统,设备,浏览器显示的特性仍是很不同的,仍是看业务场景须要兼容到什么样,尽可能不要大量处理这些事件,否则用户去浏览的时候,兼容问题较多。canvas
我处理的基本是,安卓和IOS进入全屏,退出全屏,暂停和中止这4个事件,其中进入全屏,退出全屏须要针对安卓和IOS作不一样的处理。
安卓监听进入全屏的事件:
jsvideo.addEventListener("x5videoenterfullscreen", () => { console.log("进入全屏通知"); }) jsvideo.addEventListener("x5videoexitfullscreen", () => { console.log("退出全屏通知"); })
IOS监听进入全屏的事件:
jsvideo.addEventListener("webkitbeginfullscreen", () => { console.log("进入全屏通知"); }) jsvideo.addEventListener("webkitendfullscreen", () => { console.log("退出全屏通知"); })
监听暂停事件
jsvideo.addEventListener('pause', () => { console.log('暂停了') })
监听中止事件
jsvideo.addEventListener('ended', () => {
console.log('中止了22')
})
重头戏来了,相信这个这个问题已困扰无数的前端开发人员,再搜寻这个问题的解决方法时,几乎全部的文章都是告诉你android下,播放器的控件是去不了的。其实彷佛确实是这样的,但后边在的android下,也是没有控制条的。最初看到那些H5视频我首先并无去看他们的内容多么新颖,传播量多么广,我是第一时间测试了android下的兼容问题,发现并无出现控制条。在我研究半天未果时,在一篇技术帖中看到说:因是腾讯本身的项目,微信是腾讯本身的,他们在浏览器里作了一些配置,对旗下出品的H5有所“优待”,才能确保视频的顺利“乔装”。
上面的说法我并无真正核实过,不过可使用css进行操做,我实现的方式是在video外层套一个div,height设置为100%而且设置overflow:hidden,video大于100%,就能把控制条顶到视窗外。这算是视觉的隐藏(惊喜万分~),这个时候对于video可能会形成放大,视频要留有必定的安全区,防止遮挡主体内容。对于用户体验来讲,长视频没有控制栏仍是挺不合适的,固然这个只是一个思路,具体的状况仍是看产品的形式适合哪一种。
现象描述:设置poster在不一样设备上表现不一样,浏览器没问题,可是微信浏览器和IOS就是死活显示空白,展现效果就是:孤零零的一个播放按钮展现在白纸上同样
解决方案:
var cut = function() { // 1. 建立画布 let canvas = document.createElement("canvas"); canvas.width = video.videoWidth * scale; // 2. 设定宽高比 canvas.height = video.videoHeight * scale; // 3. 将视频此刻帧数画入画布 canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); let img = document.createElement("img"); img.src = canvas.toDataURL("image/png"); // 4. 写入到Dom Dom.appendChild(img); }; video.addEventListener('loadeddata',cut);//在视频帧数已加载时执行截取
现象描述:第一次播放视频ok,可是在IOS12.*如下的机型,再次播放视频会出现黑屏的现象。检查代码发现,video使用了v-show
,关闭以后,对应的方法执行,可是只有声音没有图像,为啥???
解决方案:
webkit-playsinline
&& playsinline
,能保证再次进入不黑屏,可是IOS自动全屏的失效。思考:可是为啥这样子??不太符合逻辑的呢,仔细又看了代码,发现外边有v-show(代码如:代码1所示),猜想多是这样引发的,第二次使用的时候,难道IOS12.*如下的手机自己有兼容问题,所以,没有使用v-show处理,只用css处理了。,这样能保证IOS打开视频全屏,再次打开也不黑屏。根本缘由仍是有待深究的。
代码片1: <div class="video-fullscreen-mask'" v-show="!isShowVideoCover"> <video id='js-video' controls :class="{'width-auto': babyInfo.isNewModel,'height-auto': !babyInfo.isNewModel}" :poster="babyInfo.videoCover" webkit-playsinline="true" playsinline="true" x5-video-player-type="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" > <source :src="babyInfo.videoUrl"></source> </video> </div> ---- 分割线 ----- 代码片2: <div class="default-video" :class="{'video-fullscreen-mask':!isShowVideoCover}"> <video id='js-video' controls :class="{'width-auto': babyInfo.isNewModel,'height-auto': !babyInfo.isNewModel}" :poster="babyInfo.videoCover" :src="babyInfo.videoUrl" v-if="!userInfo.isApp" x5-video-player-type="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" ></video> </div>
若是你没有付费的话 从理论来讲 广告是不可避免的 可是能够经过一些方法绕过广告:
简单粗暴解决方案:
let isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) let videoContext = document.getElementById('video'); videoContext.addEventListener('ended', () => { if (!isiOS) { videoContext.play(); setTimeout(() => { videoContext.pause(); }, 100) } }
总结上面的问题,发现正是的场景下不一样设备的手机兼容状况仍是真的不同的,咱们针对特定的状况考虑一个合适的兜底方案便可,尽可能使用最保险的作法,毕竟上线尽可能保证没有bug才是极好的。
当使用video进行视频播放,相对于早期来讲,如今手机的性能愈来愈好,流量时代也要迎来5G,会愈来愈放宽限制,如今表现虽然不太同样,可是将来仍是会走向统一的。
视频播放--踩坑小计