整理浏览器的自动播放策略

1. Chrome 浏览器的自动播放策略

我们将 Chrome 的自动播放策略视为标准策略,与其有出入的我们在文章中会重点提示。

Chrome 66 之后的版本中,只有静音的自动播放是被允许的:

1
<vide src="xxx" muted autoplay></vide>

此外出现以下几种情况时,有声的自动播放是被允许的:

当用户与页面有交互后,可以调用 video.play() 方法来播放视频。或者在交互函数中创建的视频元素,此时创建的视频允许有声自动播放,比如:

1
2
3
4
5
6
7
8
9
10
function onButtonClick() {
const testContainer = document.querySelector("#test-container");
const video = document.createElement("video");
video.id = "test-video";
video.src = "https://b2b-web-vr.cdn.bcebos.com/aichuman/test3/cd0c8a3435c025410a9f0f15b64bce8b.mp4";
video.autoplay = true;
video.controls = true;
testContainer.appendChild(video);
video.play();
}

当网站的“媒体互动指数”超过了阈值,这通常表示用户之前在该网站上曾播放过有声视频,这时视频的有声自动播放是被允许的。

用户在移动设备上用户将网站添加到主屏幕,或者在桌面上安装了 PWA。

2. 微信内置浏览器中自动播放

在 IOS 微信的内置浏览器中,视频即使是静音状态也无法自动播放,甚至连视频的 loadedmetadata 事件也不会自动触发(在普通浏览器中视频加载出之后即使没有自动播放,loadedmetadata 事件也应该会触发),这就会导致一些视频库,如 YYEVA 的执行失败。

解决方案:使用 WeixinJSBridgeReady 的回调。

在微信内置浏览器中,WeixinJSBridgeReady 表示微信提供的 JS bridge 加载完成,在其回调中创建的视频是允许自动播放的,或者直接在其回调中调用视频的 play() 方法也是被允许的,同时这时视频即使没有设置静音播放也能成功自动播放

1
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
const container = document.querySelector("#test-container");
const video = document.createElement("video");
video.src = "https://b2b-web-vr.cdn.bcebos.com/aichuman/test3/cd0c8a3435c025410a9f0f15b64bce8b.mp4";
video.autoplay = true;
video.controls = true;
video.playsinline = true
// video.muted = true; // 即使视频不设置静音太

container.appendChild(video);

video.addEventListener("loadedmetadata", (event) => {
console.log(
"The duration and dimensions of the media and tracks are now known.",
);
});

function doPlay() {
WeixinJSBridge.invoke('getNetworkType', {}, function (e) {
// 必须在 WeixinJSBridge 的回调函数中调用 `video.play()` 才生效,这是微信的限制
video.play();
});
}

// 在 WeixinJSBridge 加载成功后直接播放
if (window.WeixinJSBridge) {
doPlay();
}
// 否则,等 WeixinJSBridge 加载成功
else {
document.addEventListener('WeixinJSBridgeReady', ()=>{
console.log("on WeixinJSBridgeReady")
doPlay()
// 你也可以直接在这里调用 video.play()
}, false);
}

或者控制页面中已有的 video 元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const video = docuemnt.querySelector("#video");

function doPlay() {
WeixinJSBridge.invoke('getNetworkType', {}, function (e) {
video.play();
});
}

if (window.WeixinJSBridge) {
doPlay();
}
else {
document.addEventListener('WeixinJSBridgeReady', ()=>{
console.log("on WeixinJSBridgeReady")
doPlay()
}, false);
}

在 Android 的微信浏览器中同样无法自动播放,并且 WeixinJSBridgeReady 并不会被触发,因此我们没办法进行自动播放(参考了多个网站,都没有在微信做自动播放),只能引导用户手动播放。

3. 夸克的自动播放策略

在 IOS 下:

  • 视频播放器会被拦截
  • 静音和非静音视频均不允许自动播放;
  • muted 的设置是无效的,即使后续用户播放了视频,也是带有声音的;
  • JS 可以直接调用 video.play() 来播放视频,无需用户交互;
  • loop 无效;
  • 多音频和视频播放:
    • 有声视频和音频之间会互相暂停;
    • 被迫暂停后不会触发 pause 事件;

在 Android 下:

  • 视频播放器会被拦截,yyeva 失效;
  • 符合标准策略;
  • 多音频和视频播放:
    • 有声视频和音频之间会互相暂停;
    • 被迫暂停后会触发 pause 事件;

4. UC

在 iOS 下:

  • 视频播放器会被拦截;
  • 静音和非静音视频均不允许自动播放;
  • muted 的设置是无效的,即使后续用户播放了视频,也是带有声音的;
  • JS 直接调用 video.play() 没有触发报错;
  • 多音频和视频播放:
    • 当一个视频在播放中时,播放另一个视频时会触发 JS 报错;
    • 当视频在播放中时播放音频,视频会被暂停,反之亦然;
    • 视频被迫暂停后会触发 pause 事件;

在 Android 下:

  • 可以使用 renderer="standard" 防止播放器被浏览器拦截;
  • 符合标准策略;
  • 多音频和视频播放:
    • 同一个页面如果存在多个音频或视频,其中一个播放后,其他的视频会被暂停,并且不会触发 pause 事件,无论是否有声(yyeva 在播放中会出现突然暂停但是语音仍播放的情况);

4. 百度 APP

在 iOS 下:

  • 即使视频不静音也能自动播放;
  • 可以直接在 JS 中调用 video.play()
  • 多音频和视频播放:
    • 有声视频点击播放,或者出发循环播放时,会暂停所有音频的播放;
    • 音频的播放不会打断有声视频的播放;
    • 无声视频和音频之间不会互相干扰播放状态;
    • 多个有声视频同时播放时,当前播放的有声视频会暂停其他视频的播放;
    • 视频被迫暂停时会触发 pause 事件;

在 Android 下:

  • 即使视频不静音也能自动播放;
  • 可以直接在 JS 中调用 video.play()
  • 多音频和视频播放:
    • 当多个有声视频同时播放时,最新播放的有声视频会暂停上一个有声视频;
    • 当视频为 muted 时,视频之间的播放不受影响,即使用户手动将 control 上的静音按钮取消,也仍然能同时播放多个有声视频;
    • 音频会暂停有声视频的播放,无声视频不受影响;

yyeva 卡住的根因:多个视频同时加载