我正在得到错误信息..
DOMException: play()失败,因为用户没有首先与文档交互。
..当使用Chrome 66版本在桌面上播放视频时。
我确实发现一个广告开始自动播放在一个网站上,但使用以下HTML:
<video
title="Advertisement"
webkit-playsinline="true"
playsinline="true"
style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
src="http://ds.serving-sys.com/BurstingRes/Site-2500/Type-16/1ff26f6a-aa27-4b30-a264-df2173c79623.mp4"
autoplay=""></video>
那么,绕过Chrome v66的自动播放拦截器真的像添加webkit-playsinline="true", playsinline="true"和autoplay=""属性<video>元素一样简单吗?这有什么负面影响吗?
回答眼前的问题…
不,只有这些属性是不够的,为了能够自动播放带有音频的媒体,你需要在你的文档上注册一个用户手势。
但是,这个限制是非常弱的:如果你确实在父文档上接收到这个user-gesture,并且你的视频是从iframe加载的,那么你可以播放它…
以这把小提琴为例,它只是
<video src="myvidwithsound.webm" autoplay=""></video>
在第一次加载时,如果你没有点击任何地方,它将不会运行,因为我们还没有注册任何事件。
但是,一旦单击“Run”按钮,父文档(jsfiddle.net)就会接收到一个用户手势,现在视频就可以播放了,尽管从技术上讲它是加载在另一个文档中的。
但是下面的代码段(因为它需要您实际单击运行代码段按钮)将自动播放。
<video src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" autoplay=""></video> .
这意味着您的广告可能能够播放,因为您确实向主页提供了用户手势。
现在,请注意,Safari和Mobile Chrome有比这更严格的规则,并要求您至少在用户事件处理程序本身的<video>或<audio>元素上以编程方式触发一次play()方法。
btn。Onclick = e => {
//将MediaElement标记为用户批准的
vid.play () () = > vid.pause ());
//现在我们可以在任何时候用这个MediaElement做任何我们想做的事情
setTimeout(()=> vid.play(), 3000);
};
<button id="btn">play in 3s</button>
<视频
src = " https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm " id = "视频" > < /视频>
如果你不需要音频,那就不要把它附加到你的媒体上,只有视频轨道的视频也可以自动播放,这将减少用户的带宽使用。
在chrome 66更新后,要使html 5元素自动播放,您只需要将静音属性添加到视频元素。
现在的视频HTML
<视频
title =“广告”
webkit-playsinline = " true "
playsinline = " true "
Style ="background-color: rgb(0,0,0); "位置:绝对的;宽度:640 px;身高:360 px;“
src = " http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 "
视频播放= " " > < / >
只需要静音="静音"
<视频
title =“广告”
Style ="background-color: rgb(0,0,0); "位置:绝对的;宽度:640 px;身高:360 px;“
src = " http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 "
播放= " true "
沉默= "低调" > < /视频>
我相信chrome 66的更新是为了阻止标签在用户标签上产生随机噪音。这就是为什么静音属性使自动播放再次工作。
扩展DOM元素,处理错误,优雅地降级
下面我使用原型函数来包装原生DOM播放函数,获取它的承诺,然后在浏览器抛出异常时将其降级为播放按钮。这个扩展解决了浏览器的缺点,是即插即用的任何页面与目标元素的知识(s)。
// JavaScript
// Wrap the native DOM audio element play function and handle any autoplay errors
Audio.prototype.play = (function(play) {
return function () {
var audio = this,
args = arguments,
promise = play.apply(audio, args);
if (promise !== undefined) {
promise.catch(_ => {
// Autoplay was prevented. This is optional, but add a button to start playing.
var el = document.createElement("button");
el.innerHTML = "Play";
el.addEventListener("click", function(){play.apply(audio, args);});
this.parentNode.insertBefore(el, this.nextSibling)
});
}
};
})(Audio.prototype.play);
// Try automatically playing our audio via script. This would normally trigger and error.
document.getElementById('MyAudioElement').play()
<!-- HTML -->
<audio id="MyAudioElement" autoplay>
<source src="https://www.w3schools.com/html/horse.ogg" type="audio/ogg">
<source src="https://www.w3schools.com/html/horse.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
根据新的浏览器策略,在播放Audio元素之前,用户必须首先与DOM交互。
如果你想在页面加载中播放媒体,那么你可以简单地添加自动播放属性到HTML中的音频元素,就像这样
<video id="video" src="./music.mp4" autoplay> .
或者如果你不想做自动播放,那么你可以使用Javascript处理这个。由于autoplay属性设置为true,媒体将被播放,我们可以简单地静音媒体。
document.getElementById('video').autoplay = true;
document.getElementById('video').muted = true;
小鬼:现在不管你什么时候播放媒体,别忘了把静音属性设为false。像这样
document.getElementById('video').muted = false;
document.getElementById('video').play();
或者,您还可以显示一个简单的弹出窗口,用户将单击模式中的允许按钮。因此,他首先与DOM交互,然后您不需要做任何事情
我得到了这个错误
DOMException: play()失败,因为用户没有首先与文档交互。
下面是我在Angular项目中所做的
关键点:永远不要假设视频会播放,当视频没有真正播放时,不要显示暂停按钮。
你应该总是查看play函数返回的Promise,看看它是否被拒绝了:
ngOnInit(): void{
this.ensureVideoPlays();
}
private ensureVideoPlays(): void{
const video = document.querySelector("video");
if(!video) return;
const promise = video.play();
if(promise !== undefined){
promise.then(() => {
// Autoplay started
}).catch(error => {
// Autoplay was prevented.
video.muted = true;
video.play();
});
}
}
来源:自动播放策略