Background
Since Chrome version 66, videos that should autoplay on my site may be prevented from playing if the user haven't been on my site before.
<video src="..." autoplay></video>
Question
How do I detect if the video autoplay was disabled? And what can I do about it?
The autoplay
attribute
According to web standard specifications, the autoplay attribute should only be a hint for what the browser should to with the media element. Neither of W3 of WHATWG web specifications mentions anything about when to prevent autoplay for media, which means that each browser probably have different implementations.
Autoplay policies
Autoplay policies implemented by each browser now govern whether video should be allowed to autoplay.
Best practices
I'll try to cover what the best practices are and what you can do in this section.
Detecting if autoplay is disabled
Instead of using autoplay
on your element, you can use the play()
method on the video
and audio
element to start playing your media. The play()
method returns a promise in modern browsers (all according to the spec). If the promise rejects, it can indicate that autoplay is disabled in the current browser on your site.
can-autoplay is a library solely for detecting autoplay features for both video and audio elements.
If autoplay is disabled
The good thing is that when you know that autoplay is disabled you can, in some browsers, then mute the video and try the play()
method again, while showing something in the UI that says that the video is playing while muted.
var video = document.querySelector('video');
var promise = video.play();
if (promise !== undefined) {
promise.then(_ => {
// Autoplay started!
}).catch(error => {
// Show something in the UI that the video is muted
video.muted = true;
video.play();
});
}
<video src="https://www.w3schools.com/tags/movie.ogg" controls></video>
For me best solution was:
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());