video在各终端适配
# 前言
在项目开发中经常碰到 video 相关的情景,随着对 video 的深入发现在不同终端不同情景会产生各种莫名其妙之坑。于是本文应对此作顺理,为未来作瞄点 review。
# 视频编码问题
当前(2021)video 支持三种编码格式:
- MP4\AVC\MPEG4(推荐)
带有 H.264 视频编码(收费)+AAC 音频编码的 MPEG4 文件(收费)
- Webm
带有 VP8 视频编码(免费)+Vorbis 音频编码的 WebM 格式(免费)
- OGG
带有 Theora 视频编码(免费)+Vorbis 音频编码的 Ogg 文件(免费)
当前阶段(2021 年)实战可得知,使用 H.264/AVC 编码格式的视频基本兼容所有终端(桌面\web\wap)的 video 使用。
在实际开发中,如果碰到使用 video 播放视频时,video 显示黑屏、无画面,又或者是视频在 pc 端可以播放视频,而在移动端的某些机型无法播放视频的情况,基本可以断定是视频编码格式不支持引起的了。在此情况推荐将视频源转码为 H.264/AVC 格式即可。
# autoplay 自动播放
在标准规范中,video 设置 autoplay 后会自动播放的。
在实际开发中,由于大视频时代,大视频高带宽的费用是显而易见的,于是诸多浏览器产商都对 audio、video 等做了限定,设置了不允许音频、视频媒体在进入页面就自动播放,也不能直接使用代码模仿点击触发播放。
终端差异:
PC 端:各浏览器自动播放差强人意,不过设置 muted 后可以静音自动播放
移动端:预期效果基本相似,都需有触发机制
- android:
- 设置 muted 不能自动播放
- 除了 wechat app 通过 JSAPI 监听 WeixinJSBridgeReady 可触发视频、音频自动播放外,必须
用户主动触发
事件调用 play()。且 android 端各机型样式各异。
- ios:
- 设置 muted 不能自动播放
- 除了 wechat app 通过 JSAPI 监听 WeixinJSBridgeReady 可触发视频、音频自动播放外,必须
用户主动触发
事件调用 play()。且 android 端各机型样式各异。
- android:
/* wechat terminal */
document.addEventListener(
"WeixinJSBridgeReady",
function() {
document.getElementById("video").play();
},
false
);
2
3
4
5
6
7
8
# 缓存视频源
preload :规定在页面加载后载入视频。如果设置了 autoplay 属性,则忽略该属性。
- meta:当页面加载后只载入元数据
- none:当页面加载后不载入视频
- auto:当页面加载后载入整个视频
autobuffer :设置为浏览器缓冲方式,true 为即使没有设置自动播放也会自动开始缓存,一直缓存到资源缓存完整;不设置 autoplay 属性才有效。
# 浏览器全屏播放 && 层级顶层问题
移动端浏览器中的 video 元素是比较特别的,早期无论是在 iOS 还是 Android 的浏览器中,它都位于页面的最顶层,无法被遮挡。后来,这个问题在 iOS 下得到了解决。但是对 Android 的大部分浏览器来说,问题仍然存在。X5 是腾讯基于 Webkit 开发的浏览器内核,应用于 Android 端的微信、QQ、QQ 浏览器等应用。它提供了一种名叫「同层播放器」的特殊 video 元素以解决遮挡问题。
# ios 全屏播放
在 iOS 上播放视频系统将会默认使用横屏全屏模式进行播放,想要禁止该能力,想使用页内播放模式,需要在 video 添加属性声明:
ios10&&ios10+,使用 playsinline
ios9&&ios9 以前,使用 webkit-playsinline
x-webkit-airplay="allow":支持 ios 的 AirPlay 功能,支持小窗内播放
# x5 内核浏览器同屏播放
x5 浏览器使用被叫同层播放器特殊的video
元素,让播放器处于页面上与页面同级显示,需要添加一下属性:
x5-webkit-playsinline : 将视频限定于页面内部播放。不要与
x5-video-player-type='h5-page'
或x5-video-player-type='h5'
共存。x5-video-player-type="h5" : 解决了视频层级过高的问题,但出现了点击播放自动进入全屏的问题。因此还需要监听 x5 的全屏事件进行适配。
x5-video-player-type="h5-page" : 解决了视频层级过高的问题,视频播放也不会立刻进入全屏状态。
另外 x5 浏览器全屏播放还需要配合几个参数适配
x5-video-player-fullscreen="true" : true 是防止横屏。IOS 微信浏览器是 Chrome 的内核,相关的属性都支持,也是为什么 X5 同层播放不支持的原因。安卓微信浏览器是 X5 内核,一些属性标签比如 playsinline 就不支持,所以始终全屏。
x5-video-orientation="portrait|landscape" : 设置视频竖屏横屏播放。protrait:竖屏;landscape:横屏。
# app 适配 video 支持 playsinline
ios 端适配video
为页内播放器需要添加属性playsinline
、webkit-playsinline
。
Android 端适配video
为页内播放器,目前 x5 系浏览器使用同层播放器
技术让页内播放器成为可能,且需添加属性x5-video-playsinline
或x5-video-player-type="h5
、x5-video-player-type="h5-page"
来配置支持。
另外第三方 app 想要让webview
支持页内video
为页内播放器,则需要 app 的 webview 设置webview.allowsInlineMediaPlayback = YES
。
# poster 海报
video
在播放之前有一个视频源预加载的过程,若碰上网络不好又或是视频源资源庞大等情况,用户体验糟糕透顶了。
为了提升用户体验,可在video
标签上添加poster
属性来展示视频海报的略缩图片:<video poster="xxx.jpg"></video>
。
然鹅在移动端 poster 在不同终端又形态各异了。
实测发现,ios 端完美支持 poster 属性,而 android 端展现效果千奇百怪有的机型直接失效。
因此,推荐使用在 video 上 设置一张 img 图片来替代 video 的 posterd 的海报展示功能。
# 视频位置 && 伸缩状态
video
视频
# 兼容性
注意:IE8 及以前的版本 不支持
<video>
标签
浏览器 | MP4(MPEG4) | WebM | Ogg |
---|---|---|---|
Internet Explorer | Yes | No | No |
Chrome | Yes | Yes | Yes |
FireFox | Yes 从 21 版本开始,Linux firefox 30 开始 | Yes | Yes |
Safair | Yes | No | No |
Opera | Yes 从 25 版本开始 | No | No |
# 移动端 canvas
在实战过程中发现,canvas 渲染 video 的效果差强人意。在移动 app 包括 QQ、wechat、自带浏览器以及第三方浏览器实测中发现:
- ios 端 各 app 支持 canvas 渲染 video,且需要 video 编码格式为 H.264
- android 端
- 暂测华为各 app 支持
- 暂测小米、vivo 的 QQ、wechat 可行,自带浏览器及第三方浏览器不可行
# video 监听结束
video 在非loop
模式下支持使用onended
监听视频结束
document.querySelector.addEventListener("ended", function() {});
# jQuery 操作 video 问题
暂无~
# css 相关 的 video 问题
/*
隐藏下载按钮(原理:控制条面板设的长一些,超出的隐藏)
另外 pc 端 需要video标签添加属性禁用下载按钮 controlsList="nodownload"
*/
@mixin videoNoDownload() {
&::-internal-media-controls-download-button {
display: none;
}
&::-webkit-media-controls-panel {
width: calc(100% + 30px);
}
&::-webkit-media-controls-enclosure {
overflow: hidden;
}
}
/* 禁用全屏按钮 */
@mixin videoNoFullscreen() {
&::-webkit-media-controls-fullscreen-button {
display: none;
}
}
video {
width: 100%;
height: 100%;
/* video 无法铺满整个屏幕 */
object-fit: fill;
/* video 默认全屏居中显示改为水平居中垂直置顶显示 */
object-position: top center;
@include videoNoDownload();
@include videoNoFullscreen();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 基本使用
最后的最后贴一个 video 基本模板
# 基本使用
- pc 端:
<video width="352" height="264" controls autobuffer controlsList="nodownload">
<source src="video/hjh.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'></source>
</video>
2
3
- h5 端:
<div class="bg-p2">
<div class="jy-player">
<video
preload="auto"
playsinline
webkit-playsinline
x-webkit-airplay="allow"
x5-video-player-type="h5"
x5-video-player-fullscreen
x5-video-orientation="portraint"
width="100%"
height="100%"
style="object-fit:fill"
class="player"
id="player"
>
<source src="./media/v.mp4" type="video/mp4" />
</video>
</div>
<div class="jy-danmu" id="danmuStage"></div>
<div class="btn-play" id="btnPlayer"></div>
</div>
<script>
// 如有需要需app设置
// webview.allowsInlineMediaPlayback = YES;
function initVideo(id) {
var video = document.getElementById(id),
videoFlag = false;
video.addEventListener(
"canplay",
function() {
video.play();
},
false
);
document.addEventListener(
"WeixinJSBridgeReady",
function() {
video.play();
},
false
);
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46