H5的视频解决方案(1) —— mobile video内联播放

1. mobile内联播放

内联播放指的是视频在文档流中直接进行播放,不会弹出新的播放窗口的方式。

<video id="video"
  style="object-fit:fill"
  preload="auto"
  webkit-playsinline="true" 
  playsinline 
  x5-video-player-type="h5"
  x5-video-player-fullscreen="true"
  x5-video-orientation="portraint"
  src="video.mp4" />
</video>
属性 含义
object-fit fill 或 cover或 contain… 视频填充模式,这三个最常用,fill会被拉伸,可以在css文件中设置。
preload auto 或 metadata 或 none 该属性在某些情况下被忽略

关于视频还有很多属性,请参考:
http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp

http://www.runoob.com/tags/ref-av-dom.html

剩下几个属性才是内联播放的关键,在下文中详细介绍:

(1) webkit-playsinline和playsinline

在手机浏览器和QQ等App中播放H5视频,系统会自动接管进行全屏播放。显然,在很多场景中,我们需要在H5的页面中进行播放,则需要加上webkit-playsinline,在iOS10之后需要加上playsinline。所以,建议同时加上这两个属性。

(2) android微信

按照上述属性设置之后,大多数情况都可以满足,唯独android的微信。它使用的是腾讯x5内核,不遵循X5web标准,会强制全屏。

这个是腾讯H5同层播放器接入规范:
https://x5.tencent.com/tbs/guide/video.html

x5-video-player-type="h5"启用H5同层播放器

x5-video-player-fullscreen="true"视频播放时将会进入到全屏模式。

x5-video-player-fullscreen="portraint"声明播放器支持的方向,此属性只在声明了x5-video-player-type=”h5”情况下生效。

在其他资料中,常常到这里就结束了。亲测根本没有办法实现。播放时,上下都是黑色,视频在中间。

根据腾讯的X5同层播放器试用报告:
https://x5.tencent.com/tbs/guide/web/x5-video.html才找到了实现方式。
【强烈推荐这篇文章】还讲解了如果增加topbar等问题。

接下来,通过这篇文章提供的方法继续。

按照官方文档所述,只要修改video元素的「object-position」属性,就可以修改视频部分的显示位置,但实际上还要把video元素的宽高设成屏幕的宽高才行。

官方提供了两个事件回调

  • x5videoenterfullscreen进入全屏通知
  • x5videoexitfullscreen退出全屏通知
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>android wechat playsinline</title>
  <style>
    body{
      margin: 0;
      background: wheat;
    }
    .player{
      width: 100%;
      height: 300px;   //有的安卓浏览器不支持vw,使用px优雅降级
      height: 56.25vw; // 16:9
      position: relative;
    }
    .player .video{
      width: 100%;
      height: 100%;
      object-position: center top;
    }
    .content{
      text-align: center;
    }
  </style>
</head>
<body>
  <div>
    <div class="player">
      <video id="video" class="video" width="1" height="1" preload="auto" style="object-fit:contain;height:300px;height: 56.25vw;" webkit-playsinline="true" playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" >
        <source type="audio/mp4" src="https://images.apple.com/media/us/iphone-7/2016/5937a0dc_edb0_4343_af1c_41ff71808fe5/camera/4k-footage/iphone7-4k-footage-cc-us-20160907_1280x720h.mp4">
      </video>
    </div>
    <div class="content">
      <p>hello content</p>
      <button onclick="document.getElementById('video').play();">play</button>
    </div>
  </div>
  <script>
    var myPlayer = document.getElementById('video');
    myPlayer.addEventListener('x5videoenterfullscreen',function(){
      myPlayer.style.width = window.screen.width + 'px';
      myPlayer.style.height = window.screen.height + 'px';
    });
    myPlayer.addEventListener('x5videoexitfullscreen',function(){
      myPlayer.style.width = myPlayer.style.height = "";
    },false);
  </script>

</body>
</html>

这里写图片描述

测试这个方案是可行的。

(3) 最佳实践

上述只是对内联播放的测试,但并非项目实践。

在手机上如果视频没有播放过不会显示出来,这个区域会是空的,video有poster属性可以配置封面,但是安卓的一些浏览器不支持。所以,为了更好的兼容性,需要手动添加封面。
这里写图片描述

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>android wechat playsinline demo</title>
  <style>
    *{
      box-sizing: border-box;
    }
    body{
      margin: 0;
      background: wheat;
    }
    .player{
      width: 100%;
      height: 300px;
      height: 56.25vw;
      position: relative;
    }
    .player .video{
      width: 100%;
      height: 100%;
    }
    .poster{
      background:url('http://via.placeholder.com/350x150?text=poster') no-repeat center center;
      background-size: cover;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
    }
    .poster::after{
      content: '';
      width: 50px;
      height: 50px;
      background: url("https://milklife.com/sites/all/themes/breakfast/owl-carousel/[email protected]") no-repeat;
      background-size: contain;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      -webkit-transform: translate(-50%,-50%);
      -moz-transform: translate(-50%,-50%);
      -o-transform: translate(-50%,-50%);
      -ms-transform: translate(-50%,-50%);
    }
    .fullscreen .player{
      /* margin-top: 80px; */
    }
    .fullscreen video{
      object-position: center 0;
      height: 0.5625vw;
    }
    .content{
      text-align: center;
    }
  </style>
</head>
<body>
  <div>
    <div class="player">
      <video id="video" class="video" width="1" height="1" preload="auto" style="object-fit:contain" webkit-playsinline="true" playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" >
        <source type="audio/mp4" src="https://images.apple.com/media/us/iphone-7/2016/5937a0dc_edb0_4343_af1c_41ff71808fe5/camera/4k-footage/iphone7-4k-footage-cc-us-20160907_1280x720h.mp4">
      </video>
      <div id="poster" class="poster">
      </div>
    </div>
    <div class="content">
      <p>hello content</p>
    </div>
  </div>
  <script>
    var myPlayer = document.getElementById('video');
    document.getElementById("poster").addEventListener("click", function(){
      myPlayer.play();
      document.getElementById('poster').style.display='none';
    });
    //x5
    myPlayer.addEventListener('x5videoenterfullscreen',function(){
      myPlayer.style.width = window.screen.width + 'px';
      myPlayer.style.height = window.screen.height + 'px';
      document.body.classList.add('fullscreen');
      document.getElementById('poster').style.display='none';
    });
    myPlayer.addEventListener('x5videoexitfullscreen',function(){
      myPlayer.style.width = myPlayer.style.height = "";
      document.body.classList.remove('fullscreen');
      document.getElementById('poster').style.display='block';
    },false);
  </script>

</body>
</html>

以上代码是实现视频播放的雏形。可以根据项目的实际情况,比如在视频播放完成的时候再将封面加回来等。

(4) 其他尝试

为了解决用户点击播放按钮,但视频还未加载到可播放的程度。

【功能】点击封面播放,如果此时视频可以播放则播放,不可以显示加载中,等加载完成后开始播放。

【实现】通过video的canplay属性判断是否加载完成,并注册canplay事件,在加载完成后播放。

【失败原因】iOS不支持canplay事件注册,在安卓上测试是可以的。

尝试用loadeddata实现全部加载完了再播放iOS也不支持,安卓支持。

(5) 仍存在的问题

目前在上文第三小节中提到的最佳实践已知在华为P9的系统自带浏览器上不能实现内联播放。但是华为CAZ-AL 10却是可以的,包括在UC浏览器等其他环境也是可以的。如果有解决的方法,请联系我,或在评论中留言。

猜你喜欢

转载自blog.csdn.net/joyce_lcy/article/details/81391142