移动端视频播放踩坑

H5 中很多场景交互较少强调动画展示的场景都可以借助视频实现,而且能够实现 100% 视觉还原😝,对于设计师来说最终呈现效果可控,对开发来说极大地降低了工作量,运营因为工期减少也会开心,简直是一石三鸟的事情!不过移动端 video 还是有很多坑的,以下是我做的一点调研。

去除 video 的播放控件

video 标签不设置 control 属性,在 iOS 与 Android 上也会出现播放控件,并且视屏元素的层级调整到最高,上方不能覆盖有其他元素。

Canvas 方案

可使用 pixi.js 播放 video 的功能,将视频画面用 Canvas 输出。

let app = new PIXI.Application({
    view: document.getElementById('stage'),
    forceCanvas: true,
});
// create a video texture from a path
let texture = PIXI.Texture.fromVideo(require('assets/video/video.mp4'));
// create a new Sprite using the video texture (yes it's that easy)
let videoSprite = new PIXI.Sprite(texture);
app.stage.addChild(videoSprite);

该方式在 iOS 高德端内还是会展示播放控件,至于 Android 端内表现良好,但是因为前者的问题所以该方案还是被舍弃了。

iOS 微信端内

使用 playsinline="true"webkit-playsinline="true" 属性可以使视频内联播放。iOS 10 以及之后的版本支持 playsinline="true",iOS 10 之前的版本可使用webkit-playsinline="true"

具体参考 Webkit 官方文章: New <video> Policies for iOS

<video src="video.mp4"
       playsinline="true"
       webkit-playsinline="true"
></video>

如动态添加 playsinlinewebkit-playsinline 无效,需提前在HTML 中定义好。

上述属性配置需 iOS 中 WebView 中需要有相应的设置支持,否者前端已经设置上述属性也是无效的。

iOS 高德端内

使用 enableInlineVideo 插件,可实现端内无控件播放,

<video src="video.mp4"
       id="video"
       playsinline="true"
       webkit-playsinline="true">
</video>

<script>  
    let video = document.querySelector('#video');
    video.play();
    enableInlineVideo(video);
</script>

<style>
.IIV::-webkit-media-controls-play-button,
.IIV::-webkit-media-controls-start-playback-button {
    opacity: 0;
    pointer-events: none;
    width: 5px;
    object-position: center center;
}
</style>

Android 高德端内

目前各个方案都能很好的隐藏播放控件。

Android 微信端内

腾讯浏览器 X5 内核 提供了 H5 同层播放器接入规范,由于微信内置浏览器使用的是腾讯浏览器 X5 内核,可使用其一些私有属性。

x5-video-player-type

通过 video 属性 x5-video-player-type声明启用同层 H5 播放器。

<video src="http://xxx.mp4" x5-video-player-type="h5"/>

这个属性需要在播放前设置好,播放之后设置无效。

x5-video-player-fullscreen

x5-video-player-fullscreen 可使视频播放时进入到全屏模式。如果不申明此属性,页面得到视口区域为原始视口大小(视频未播放前),比如在微信里,会有一个常驻的标题栏,如果不声明此属性,这个标题栏高度不会给页面,播放时会平均分为两块(上下黑块)。

<video id="video" src="xxx" x5-video-player-type="h5" x5-video-player-fullscreen="true"/>

声明此属性,需要页面自己重新适配新的视口大小变化。可以通过监听resize 事件来实现。

window.onresize = function(){
    video.style.width = window.innerWidth + "px";
    video.style.height = window.innerHeight + "px";
}

同样,这个属性需要在播放前设置好,播放之后设置无效。

特殊机型问题

魅族 Pro 6

魅族 Pro 6 在微信端内会新开一个层展示视频,且标题栏会变透明,去除属性 x5-video-player-fullscreen 也无效。

自动播放

与音频一样,视屏播放也需要用户的操作来触发,通过一些按钮来诱导用户触发视频播放。

let videoPlay = () => {
    video.play();
    document.removeEventListener('touchstart', videoPlay);
};
document.addEventListener('touchstart', videoPlay, false);

检测是否支持自动播放

play() 方法会返回一个 promise

iOS

iOS 上的 Safari 视频自动播放

iOS 10 中允许自动视频播放的两种情况:

  1. 无音轨视频
  2. 无声音视频(设置了 muted 属性)
  3. 视频元素需在是视口内且是可见的
  4. 视频元素需插入到 DOM 中

Android

Android Chrome

Chrome 53 之后也支持了同样的策略。

<video autoplay muted>
  <source src="video.webm" type="video/webm" />
  <source src="video.mp4" type="video/mp4" />
</video>

Android 其他浏览器

Firefox 和 UC 浏览器已经在 Android 上支持自动播放,无论是否静音,它们不会阻止任何类型的自动播放。

Android 高德端内

不可以自动播放,需用户手动触发。

iOS 与 Android 微信端内

在微信中集成 JS-SDK 后监听 WeixinJSBridgeReady 事件可触发视频播放,可无需经由用户操作从而实现音乐播放的目的,因该是微信内部做了处理。

document.addEventListener(
    'WeixinJSBridgeReady',
    function() {
        video.play();
    },
    false
);

预加载

如视频播放因资源未加载完毕而造成的卡顿会影响体验,需预先加载好视频文件。在PC 端可用 preload="auto" 属性实现视频的预加载。但 iOS 中 preload="auto" 属性是不生效的,可支持proload="metadata"到,同样的策略在 Android Chrome 也适用。

preload

使用 preload 可以实现资源预加载。

待验证

通过 Can I Use 查询 https://caniuse.com/#search=preload
iOS 11.3 与 Chrome 67 之后才开始支持。

<link rel="preload" href="video.mp4" as="video" type="video/mp4">

通过 JavaScript 动态添加 video 预加载:

 let link = document.createElement('link');
link.setAttribute('rel', 'preload');
link.setAttribute('href', 'video.mp4');
link.setAttribute('as', 'video');
link.setAttribute('type', 'video/mp4');
document.head.appendChild(link);

Android Chrome

fetch

待验证

https://developers.google.com/web/fundamentals/media/fast-playback-with-video-preload

样式

隐藏控件

非移动端直接去除 control 属性即可,但是移动端仅仅依靠这是不行的。

至于移动端这里还得分情况,Android 上的 Chrome 其实只需不声明 control 属性即可。即便申明了用如下 CSS 也可移除播放控件。

video::-webkit-media-controls-panel {
    display:none !important;
}

iOS 上的 Safari 上的播放控件貌似是无法使用 CSS 隐藏掉的,需去除 control 属性,但是只要播放后还是会进入全屏模式,这时候需要添加 playsinline,不过这种方案与 CSS 没啥关系了。

所以单纯依靠 CSS 去除播放控件也是不可行的,其余端的测试也没继续下去。

https://stackoverflow.com/questions/15126921/why-do-no-user-agents-implement-the-css-cursor-style-for-video-elements/15145555#15145555

测试机型

机型 高德端内 微信端内 说明
iPhone 8 Plus ✔️ ✔️
iPhone X ✔️ ✔️
Galaxy Note 4 ✔️ ✔️
红米 Note 4 ✔️ ✔️
魅族 Pro 6 ✔️ ✔️* Title Bar 透明
Galaxy S6 edge 高德 App 会自动假死退出,无法完成测试

参考

发表评论

电子邮件地址不会被公开。 必填项已用*标注