如何检测 Chrome/Safari/Firefox 是否阻止了视频的自动播放?
How to detect if Chrome/Safari/Firefox prevented autoplay for video?
背景
自 Chrome 版本 66 起,如果用户之前没有访问过我的网站,则本应在我的网站上自动播放的视频可能无法播放。
<video src="..." autoplay></video>
问题
如何检测视频自动播放是否被禁用?我该怎么办?
autoplay
属性
根据网络标准规范,autoplay 属性应该只是一个提示 浏览器应该如何处理媒体元素。 W3 of WHATWG 网络规范都没有提及何时阻止媒体自动播放,这意味着每个浏览器可能有不同的实现。
自动播放政策
每个浏览器实施的自动播放政策现在决定是否允许视频自动播放。
Chrome 使用他们称为媒体的东西
参与指数,您可以阅读更多相关信息 here and their autoplay policy here。
Safari 开发者制作了 post on webkit.org
关于这个。
Firefox 似乎将其交由用户选择是否允许 (link)。
最佳实践
检测自动播放是否被禁用
您可以在 video
和 audio
元素上使用 play()
方法来开始播放您的媒体,而不是在您的元素上使用 autoplay
。 play()
方法 returns 现代浏览器中的承诺(全部根据规范)。如果 promise 被拒绝,则可能表示您网站上的当前浏览器已禁用自动播放。
can-autoplay 是一个专门用于检测视频和音频元素的自动播放功能的库。
如果自动播放被禁用
好处是,当您知道自动播放已禁用时,您可以在某些浏览器中将视频静音并再次尝试 play()
方法,同时在 UI 中显示一些内容说视频正在静音播放。
var video = document.querySelector('video');
var promise = video.play();
if (promise !== undefined) {
promise.then(_ => {
// Autoplay started!
}).catch(error => {
// Autoplay not allowed!
// Mute video and try to play again
video.muted = true;
video.play();
// Show something in the UI that the video is muted
});
}
<video src="https://www.w3schools.com/tags/movie.ogg" controls></video>
对我来说最好的解决方案是:
function _callback_onAutoplayBlocked() {
// do something, for example "show big play button"
}
function isSafari() {
var chr = window.navigator.userAgent.toLowerCase().indexOf("chrome") > -1;
var sfri = window.navigator.userAgent.toLowerCase().indexOf("safari") > -1;
return !chr && sfri;
}
function _checkAutoPlay(p) {
var s = window['Promise'] ? window['Promise'].toString() : '';
if (s.indexOf('function Promise()') !== -1 || s.indexOf('function ZoneAwarePromise()') !== -1) {
p.catch(function(error) {
console.error("_checkAutoPlay, error:", error)
if(error.name == "NotAllowedError") { // For Chrome/Firefox
console.error("_checkAutoPlay: error.name:", "NotAllowedError")
_callback_onAutoplayBlocked();
} else if (error.name == "AbortError" && isSafari()) { // Only for Safari
console.error("_checkAutoPlay: AbortError (Safari)")
_callback_onAutoplayBlocked();
} else {
console.error("_checkAutoPlay: happened something else ", error);
// throw error; // happened something else
}
}).then(function(){
console.log("_checkAutoPlay: then");
// Auto-play started
});
} else {
console.error("_checkAutoplay: promise could not work in your browser ", p);
}
}
var video1 = document.getElementById('video1');
_checkAutoPlay(video1.play());
背景
自 Chrome 版本 66 起,如果用户之前没有访问过我的网站,则本应在我的网站上自动播放的视频可能无法播放。
<video src="..." autoplay></video>
问题
如何检测视频自动播放是否被禁用?我该怎么办?
autoplay
属性
根据网络标准规范,autoplay 属性应该只是一个提示 浏览器应该如何处理媒体元素。 W3 of WHATWG 网络规范都没有提及何时阻止媒体自动播放,这意味着每个浏览器可能有不同的实现。
自动播放政策
每个浏览器实施的自动播放政策现在决定是否允许视频自动播放。
Chrome 使用他们称为媒体的东西 参与指数,您可以阅读更多相关信息 here and their autoplay policy here。
Safari 开发者制作了 post on webkit.org 关于这个。
Firefox 似乎将其交由用户选择是否允许 (link)。
最佳实践
检测自动播放是否被禁用
您可以在 video
和 audio
元素上使用 play()
方法来开始播放您的媒体,而不是在您的元素上使用 autoplay
。 play()
方法 returns 现代浏览器中的承诺(全部根据规范)。如果 promise 被拒绝,则可能表示您网站上的当前浏览器已禁用自动播放。
can-autoplay 是一个专门用于检测视频和音频元素的自动播放功能的库。
如果自动播放被禁用
好处是,当您知道自动播放已禁用时,您可以在某些浏览器中将视频静音并再次尝试 play()
方法,同时在 UI 中显示一些内容说视频正在静音播放。
var video = document.querySelector('video');
var promise = video.play();
if (promise !== undefined) {
promise.then(_ => {
// Autoplay started!
}).catch(error => {
// Autoplay not allowed!
// Mute video and try to play again
video.muted = true;
video.play();
// Show something in the UI that the video is muted
});
}
<video src="https://www.w3schools.com/tags/movie.ogg" controls></video>
对我来说最好的解决方案是:
function _callback_onAutoplayBlocked() {
// do something, for example "show big play button"
}
function isSafari() {
var chr = window.navigator.userAgent.toLowerCase().indexOf("chrome") > -1;
var sfri = window.navigator.userAgent.toLowerCase().indexOf("safari") > -1;
return !chr && sfri;
}
function _checkAutoPlay(p) {
var s = window['Promise'] ? window['Promise'].toString() : '';
if (s.indexOf('function Promise()') !== -1 || s.indexOf('function ZoneAwarePromise()') !== -1) {
p.catch(function(error) {
console.error("_checkAutoPlay, error:", error)
if(error.name == "NotAllowedError") { // For Chrome/Firefox
console.error("_checkAutoPlay: error.name:", "NotAllowedError")
_callback_onAutoplayBlocked();
} else if (error.name == "AbortError" && isSafari()) { // Only for Safari
console.error("_checkAutoPlay: AbortError (Safari)")
_callback_onAutoplayBlocked();
} else {
console.error("_checkAutoPlay: happened something else ", error);
// throw error; // happened something else
}
}).then(function(){
console.log("_checkAutoPlay: then");
// Auto-play started
});
} else {
console.error("_checkAutoplay: promise could not work in your browser ", p);
}
}
var video1 = document.getElementById('video1');
_checkAutoPlay(video1.play());