25

html5中video在安卓与ios实际应用中遇到的问题及解决

安卓和IOS对于html5中的video兼容一直是大问题,各种不一样,体验还很差。这段时间做一个html的video播放的时候,要求全屏展示,真是各种问题。下面就就记一下这个项目中遇到的一下手机兼容问题和对应的处理方法。查资料的过程中,发现针对于video的兼容问题还是比较多个,会罗列视频播放的通用场景和各个场景下踩过的坑,希望在需求开发的时候,能够针对合适的场景,选择合适的技术方案。有相关的补充,欢迎大家进行补充。

1. 先了解一下 Video相关的属性

  • 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就不支持,所以始终全屏。

2. 常见的各种场景

1. 自动播放

早期的安卓和IOS都需要用户手势才能自动播放,后期逐渐放宽的自动播放的策略,逐渐开始支持自动播放,当然在不同的安卓微信手机和对应的浏览器上,展示略有差异,这个没有完全清楚所以机型展示情况。

PC端的浏览器具体情况有所差别,这个没有进行深入研究,大家有采坑欢迎进行补充。

真正的做法是,检测当前的浏览器是否能支持自动播放,示例代码:

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)

2. 全屏处理

这个其实并不难,安卓和IOS,在微信环境下打开,默认应该都是全屏(不是视频占据整个手机的全屏,而是占用body内的视窗范围之内)

安卓全屏效果,没有顶部的导航栏,只有”>“ 和 ”...“,[效果如下]:
1562144522243-Android.jpeg

IOS会直接打开全屏模式。效果如下:
1561608977074-WechatIMG42.jpeg

IOS的非全屏展示。对安卓无影响 IOS效果图-如图所示:
1561603636681-WechatIMG40.jpeg

但是有的时候不想全屏展示,只需要加上webkit-playsinline && playsinline即可,视频播放不脱离文档流,进行局部播放。安卓情况下有'...', 如果安装过QQ浏览器会能进行小窗播放,悬浮在页面的最上面,这个现象符合条件都有,但是不能去掉。这个还是解决不了的,不过一般这样操作的用户还是在少数。

3. 播放控制

video 元素有提供多个行为事件供开发者控制视频播放,兼容性比较好的有 onended 、 ontimeupdate、onplay、onplaying等,有些事件在不同浏览器不同设备上的的表现情况并不一致,不同的系统,设备,浏览器显示的特性还是很不一样的,还是看业务场景需要兼容到什么样,尽量不要大量处理这些事件,不然用户去浏览的时候,兼容问题较多。

我处理的基本是,安卓和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')
})

4. 隐藏视频播放的控制条

重头戏来了,相信这个这个问题已困扰无数的前端开发人员,再搜寻这个问题的解决方法时,几乎所有的文章都是告诉你android下,播放器的控件是去不了的。其实似乎确实是这样的,但后边在的android下,也是没有控制条的。最初看到那些H5视频我首先并没有去看他们的内容多么新颖,传播量多么广,我是第一时间测试了android下的兼容问题,发现并没有出现控制条。在我研究半天未果时,在一篇技术帖中看到说:因是腾讯自己的项目,微信是腾讯自己的,他们在浏览器里做了一些配置,对旗下出品的H5有所“优待”,才能确保视频的顺利“乔装”。

上面的说法我并没有真正核实过,不过可以使用css进行操作,我实现的方式是在video外层套一个div,height设置为100%并且设置overflow:hidden,video大于100%,就能把控制条顶到视窗外。这算是视觉的隐藏(惊喜万分~),这个时候对于video可能会造成放大,视频要留有一定的安全区,防止遮挡主体内容。对于用户体验来说,长视频没有控制栏还是挺不合适的,当然这个只是一个思路,具体的情况还是看产品的形式适合哪种。

5. video设置封面显示空白

现象描述:设置poster在不同设备上表现不同,浏览器没问题,但是微信浏览器和IOS就是死活显示空白,展示效果就是:孤零零的一个播放按钮展示在白纸上一样

解决方案:

  • 方案1: 如果有视频合成的封面图,就自定义一个div,将封面放在div中,然后div盖在video的上面。
  • 方案2: 没有封面图就通过canvas截取视频第一帧作为默认显示的图片。
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);//在视频帧数已加载时执行截取

6. video在某些机型上,再次播放会黑屏,没图像只有声音

现象描述:第一次播放视频ok,但是在IOS12.*以下的机型,再次播放视频会出现黑屏的现象。检查代码发现,video使用了v-show,关闭之后,对应的方法执行,但是只有声音没有图像,为啥???

解决方案:

  • 方案1:尝试加了代码 webkit-playsinline && playsinline ,能保证再次进入不黑屏,但是IOS自动全屏的失效。

思考:但是为啥这样子??不太符合逻辑的呢,仔细又看了代码,发现外边有v-show(代码如:代码1所示),猜测可能是这样引起的,第二次使用的时候,难道IOS12.*以下的手机本身有兼容问题,因此,没有使用v-show处理,只用css处理了。,这样能保证IOS打开视频全屏,再次打开也不黑屏。根本原因还是有待深究的。

  • 方案2:没有使用v-show处理,只用css进行兼容处理(代码如:代码2所示)
代码片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>

7. 安卓手机播放结束后,会有广告弹出

如果你没有付费的话 从理论来说 广告是不可避免的 但是可以通过一些方法绕过广告:
简单粗暴解决方案:

  • 首先判断设备是安卓还是iOS
  • 在视频播放完成事件中添加,先播放视频再暂停视频即可
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)
  }
}

3. 总结

总结上面的问题,发现正是的场景下不同设备的手机兼容情况还是真的不一样的,我们针对特定的情况考虑一个合适的兜底方案即可,尽量使用最保险的做法,毕竟上线尽量保证没有bug才是极好的。

当使用video进行视频播放,相对于早期来说,现在手机的性能越来越好,流量时代也要迎来5G,会越来越放宽限制,现在表现虽然不太一样,但是未来还是会走向统一的。

参考

视频播放--踩坑小计

html5中video在安卓与ios实际应用中遇到的问题及解决

视频标签 video的一些特殊属性详解

微信中H5同层Video播放器接入教程

video 标签在微信浏览器的问题解决方法


李银凤
101 声望1 粉丝