H5 直播避坑指南

2,852 阅读7分钟
原文链接: zhuanlan.zhihu.com

本文来自“小时光茶社(Tech Teahouse)”公众号

作者简介:
文赫,2015年加入腾讯,作为前端开发工程师参与过手Q游戏公会,游戏中心,企鹅电竞等项目,具有丰富的移动端开发和直播开发经验。

导语

企鹅电竞项目,直播和视频播放是其中的核心。面对着产品同学不断的询问:为什么h5的体验这么差?为什么不能和app的播放体验保持一致?我们对着h5不明确的文档和不同浏览器的怪异表现欲哭无泪。 经过一系列的调研爬坑,斩荆披棘,我们一步步提升了体验,做到了和app基本一致的体验。在摸索优化背后,我们也想把这些问题和解决方法总结下来,让其他同学做到直播的时候可以自豪的说,这就是我们的h5直播体验

1. 自动播放问题

  • 通过autoplay属性
    视频的自动播放需要在video标签上添加autoplay属性, 如:

    <video autoplay><video/>
    

    但是在很多浏览器里,如iOS下并不支持这个属性,在iOS下必须给webview设置

    self.wView.allowsInlineMediaPlayback = YES;self.wView.mediaPlaybackRequiresUserAction = NO;
    

    才能让这个属性生效从而让用户一进入页面就开始视频的自动播放

  • 通过直接调用video.play()方法
    在一些情况下我们想加入一些判断逻辑,如判断用户网络环境,在wifi下自动播放,在4g环境下给出提示,这中情况下就适合直接选中video并调用video.play来播放视频

2. 页面内联播放问题

在iOS Safari和一些安卓的一些浏览器下播放视频的时候,不能在h5页面中播放视频,系统会自动接管视频

如果需要在h5页面内播放视频,需要在视频标签上加上 webkit-playsinline,在iOS10以后,需要加上playsinline,建议同时加上这两个属性,同时需要app支持这种模式,手Q和微信都支持这种模式

     //在html
     <video id="player" webkit-playsinline playsinline >    //在app内设置webview属性
     webview.allowsInlineMediaPlayback = YES;

3. 视频的高度问题

在安卓下,一些浏览器如QQ浏览器和UC浏览器,系统会把视频的层级调到最高,所以如果想在页面上显示dom元素,都会被视频盖住,单纯的设置该dom的z-index是无效的,如图所示

&amp;amp;amp;lt;img src="https://pic1.zhimg.com/v2-d428107a8edfd46e3b5d317ac81c51d4_b.png" data-rawwidth="400" data-rawheight="705" class="content_image" width="400"&amp;amp;amp;gt;

解决方案:

  1. 在弹出会显示在视频上方dom的时候暂停视频播放
  2. 将视频所在的dom的父元素的高度设为1
  3. 处理完弹出的事件后将视频所在的父元素高度还原

4. 视频的默认播放图标

在iOS下会有一个默认的播放图标,如图所示

&amp;amp;amp;lt;img src="https://pic3.zhimg.com/v2-c8943a84773e89ea9f36dbcd3fbcf43e_b.png" data-rawwidth="400" data-rawheight="671" class="content_image" width="400"&amp;amp;amp;gt;

在iOS都会默认显示,不能通过js控制,但是可以通过css样式将其隐藏

     video::-webkit-media-controls-start-playback-button {
             display: none;
     }

5. 视频的控制栏

在h5播放的时候,如果在video标签上设置了controls属性,则会在视频里显示控制栏

&amp;amp;amp;lt;img src="https://pic2.zhimg.com/v2-7c5186fed14cb36ca319caf980a6f7d1_b.png" data-rawwidth="400" data-rawheight="708" class="content_image" width="400"&amp;amp;amp;gt;

需要注意的是这个控制栏是系统webview自带的,无法通过css控制其样式,建议不要使用这个属性而是自己通过dom自己制作一套控制条

6. 视频的刷新

我们知道video暴露了play和pause方法来提供视频的播放和暂停,但是h5没有标准的刷新方法,如果我们想实现视频的刷新,则需要通过js实现

 var player = $('#player')[0];
 player.load();
 setTimeout(function () {
      player.play();
 })

7. 视频的全屏问题

1)全屏api

h5暴露了一个webkitRequestFullScreen方法,可以让每个dom都请求全屏,当然video标签也可以使用。

但是在测试中发现,一些安卓机不支持该属性,如小米手机,所以需要在调用的时候进行一下判断

 var player = $('#player')[0];if (player.webkitSupportsFullscreen) {
     player.webkitEnterFullscreen();
 } else {
    player.webkitRequestFullScreen();
 }

2)系统接管播放

我们上边说道调用h5的webkitRequestFullScreen方法来进入视频的全屏,那么这个方法会使浏览器完全接管视频播放,如图所示

&amp;amp;amp;lt;img src="https://pic4.zhimg.com/v2-2db19276fb7a46d23befb8771ee85077_b.png" data-rawwidth="400" data-rawheight="711" class="content_image" width="400"&amp;amp;amp;gt;

这种接管的后果是这时的我们是没有办法控制视频的播放,也没有办法在上面浮动我们的dom元素,如弹幕,礼物这些,会完全被视频盖在下面,所以我们的目标即是解决这种系统接管的问题

3)使用伪全屏(样式全屏)

样式全屏的核心是设置video标签的宽高,使其撑满整个webview,看上去像全屏一样

但是因为视频一般都是16:9的宽高比,所以在竖屏情况下不能很好的做到铺满整个屏幕

&amp;amp;amp;lt;img src="https://pic1.zhimg.com/v2-6daf7084f9f6be23bdedf8daa071dd04_b.png" data-rawwidth="400" data-rawheight="711" class="content_image" width="400"&amp;amp;amp;gt;

而一般用户进入页面基本都是竖屏,所以我们就要考虑怎么让用户在竖屏点击全屏按钮时,能体验到像终端app一样自动进入横屏全屏的体验,下面有两种方案

1.在用户点击全屏时候,通过css3属性旋转屏幕

通过css的transform,我们可以把dom元素旋转显示

通过-webkit-transform: rotate(90deg)并设置video的高度为当前webview的宽度,video的宽度为当前webview的高度来实现旋转全屏.

这种模式的显示没有太大问题,但因为是通过css控制的页面dom显示,对于原生的空间不能很好的控制,如系统的键盘

&amp;amp;amp;lt;img src="https://pic4.zhimg.com/v2-c7942f43b3e5eb1d14d351a1196191cf_b.png" data-rawwidth="400" data-rawheight="707" class="content_image" width="400"&amp;amp;amp;gt;

在拉起键盘输入弹幕的时候,键盘不受控制还是竖屏显示了 如果页面不涉及与原生组件的交互,那么这种方案是一种很可行且兼容性比较好的方案

2.用户在点击全屏时,通过js api来控制webview旋转横屏

在手Q里,我们和终端的同学合作添加了控制webview横竖屏的接口 在用户点击全屏的时候,先判断当前是否横屏

     /**
      * 是否横屏
      */
     function isHorizontal() {       
         if (window.orientation != undefined) {        
             return (window.orientation == 90 || window.orientation == -90);
         } else {         
             return window.innerWidth > window.innerHeight;
         }
     }
 //设置webview为横竖屏
  mqq.ui.setWebViewBehavior({         
       orientation: 0 //0是竖屏,1是横屏
  });

如果是竖屏则强制webview旋转进入横屏,同时监听页面的resize方法,页面横竖屏变化的时候会触发这个方法,在这个方法里再动态的调整video的宽高来铺满整个屏幕

&amp;amp;amp;lt;img src="https://pic2.zhimg.com/v2-55ebd8f3f4951c6f69c9a5368441ea29_b.jpg" data-rawwidth="711" data-rawheight="400" class="origin_image zh-lightbox-thumb" width="711" data-original="https://pic2.zhimg.com/v2-55ebd8f3f4951c6f69c9a5368441ea29_r.jpg"&amp;amp;amp;gt;

注:

之前我们发现x5插入了一段js来劫持视频的全屏的事件

&amp;amp;amp;lt;img src="https://pic1.zhimg.com/v2-6c896b1e85f536a02c6f1909c9df33a8_b.png" data-rawwidth="1345" data-rawheight="400" class="origin_image zh-lightbox-thumb" width="1345" data-original="https://pic1.zhimg.com/v2-6c896b1e85f536a02c6f1909c9df33a8_r.png"&amp;amp;amp;gt;

满足条件的video标签全屏时都会被X5接管,另外调用webkitEnterFullscreen方法时,X5也会接管播放器。

总结:

在经历过各种优化和调整后,我们可以在h5直播页做到看直播,看弹幕,发弹幕,发送礼物,表情,查看排名等各种功能,再配合上手Q里的隐藏titlebar的_wv=16777217,可以实现全屏播放效果,做到了媲美原生播放的体验。

现在的h5的播放还有很多的表现和兼容性的问题,希望这份指南可以帮你在遇到同样的坑时能尽快爬出来,并优化你的h5播放体验,吸引到更多的用户 : D

更多精彩内容欢迎关注bugly的微信公众账号:

&amp;amp;amp;lt;img src="https://pic3.zhimg.com/3f2c1b1ff77f19100358cedf3fb54616_b.jpg" class="content_image"&amp;amp;amp;gt;

腾讯 Bugly是一款专为移动开发者打造的质量监控工具,帮助开发者快速,便捷的定位线上应用崩溃的情况以及解决方案。智能合并功能帮助开发同学把每天上报的数千条 Crash 根据根因合并分类,每日日报会列出影响用户数最多的崩溃,精准定位功能帮助开发同学定位到出问题的代码行,实时上报可以在发布后快速的了解应用的质量情况,适配最新的 iOS, Android 官方操作系统,鹅厂的工程师都在使用,快来加入我们吧!