Javascript 如何处理“未捕获(承诺)DOMException:play() 失败,因为用户没有先与文档交互。” 在 Chrome 66 的桌面上?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49930680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:31:17  来源:igfitidea点击:

How to handle "Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first." on Desktop with Chrome 66?

javascriptgoogle-chromevideohtml5-video

提问by Steven

I'm getting the error message..

我收到错误消息..

Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.

Uncaught (in promise) DOMException: play() 失败,因为用户没有先与文档交互。

..when trying to play video on desktop using Chrome version 66.

..当尝试使用 Chrome 66 版在桌面上播放视频时。

I did find an ad that began playback automatically on a website however using the following HTML:

我确实找到了一个在网站上自动开始播放的广告,但使用了以下 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>

So is by-passing Chrome v66's autoplay blocker really as easy as just adding the webkit-playsinline="true", playsinline="true", and autoplay=""attributes to the <video>element? Are there any negative consequences to this?

那么,绕过Chrome的V66的自动播放拦截真的那么容易,因为只需添加webkit-playsinline="true"playsinline="true"autoplay=""属性的<video>元素?这有什么负面影响吗?

回答by Joe

To make the autoplay on html 5 elements work after the chrome 66 update you just need to add the mutedproperty to the video element.

要在 chrome 66 更新后使 html 5 元素的自动播放工作,您只需将该muted属性添加到视频元素。

So your current video HTML

所以你当前的视频 HTML

<video
    title="Advertisement"
    webkit-playsinline="true"
    playsinline="true"
    style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
    src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
    autoplay=""></video>

Just needs muted="muted"

刚需 muted="muted"

<video
    title="Advertisement"
    style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
    src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
    autoplay="true"
    muted="muted"></video>

I believe the chrome 66 update is trying to stop tabs creating random noise on the users tabs. That's why the muted property make the autoplay work again.

我相信 chrome 66 更新试图阻止标签在用户标签上产生随机噪音。这就是静音属性使自动播放再次工作的原因。

回答by Ming

  1. Open chrome://settings/content/sound
  2. Setting No user gesture is required
  3. Relaunch Chrome
  1. 打开 chrome://settings/content/sound
  2. 设置不需要用户手势
  3. 重新启动 Chrome

回答by Moiz

The best solution i found out is to mute the video

我发现的最佳解决方案是将视频静音

HTML

HTML

<video loop muted autoplay id="videomain">
  <source src="videoname.mp4" type="video/mp4">
</video>

回答by Kaiido

Answering the question at hand...
No it's not enough to have these attributes, to be able to autoplay a media with audio you need to have an user-gesture registered on your document.

回答手头的问题......
不,拥有这些属性是不够的,为了能够自动播放带有音频的媒体,您需要在文档上注册用户手势。

But, this limitation is very weak: if you did receive this user-gesture on the parent document, and your video got loaded from an iframe, then you could play it...

但是,这个限制非常弱:如果您确实在父文档上收到了这个用户手势,并且您的视频是从 iframe 加载的,那么您可以播放它...

So take for instance this fiddle, which is only

所以以这个小提琴为例,它只是

<video src="myvidwithsound.webm" autoplay=""></video>

At first load, and if you don't click anywhere, it will not run, because we don't have any event registered yet.
But once you click the "Run"button, then the parent document (jsfiddle.net) did receive an user-gesture, and now the video plays, even though it is technically loaded in a different document.

在第一次加载时,如果你没有点击任何地方,它就不会运行,因为我们还没有注册任何事件。
但是,一旦您单击“运行”按钮,父文档 (jsfiddle.net) 就会收到用户手势,现在可以播放视频,即使它在技术上已加载到不同的文档中。

But the following snippet, since it requires you to actually click the Run code snippetbutton, will autoplay.

但是下面的代码片段,因为它需要你实际点击运行代码片段按钮,将自动播放。

<video src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" autoplay=""></video>

This means that your ad was probably able to play because you did provide an user-gesture to the main page.

这意味着您的广告可能能够播放,因为您确实向主页提供了用户手势。



Now, note that Safari and Mobile Chrome have stricter rules than that, and will require you to actually trigger at least once the play()method programmatically on the <video>or <audio>element from the user-event handler itself.

现在,请注意 Safari 和 Mobile Chrome 具有比这更严格的规则,并且将要求您在用户事件处理程序本身play()<video>or<audio>元素上以编程方式至少实际触发一次该方法。

btn.onclick = e => {
  // mark our MediaElement as user-approved
  vid.play().then(()=>vid.pause());
  // now we can do whatever we want at any time with this MediaElement
  setTimeout(()=> vid.play(), 3000);
};
<button id="btn">play in 3s</button>
<video
  src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" id="vid"></video>

And if you don't need the audio, then simply don't attach it to your media, a video with only a video track is also allowed to autoplay, and will reduce your user's bandwidth usage.

如果您不需要音频,那么只需不要将其附加到您的媒体上,也可以自动播放只有视频轨道的视频,这将减少您用户的带宽使用。

回答by Eutrepe

For me (in Angular project) this code helped:

对我来说(在 Angular 项目中)这段代码有帮助:

In HTML you should add autoplay muted

在 HTML 中,您应该添加 autoplay muted

In JS/TS

在 JS/TS

playVideo() {
    const media = this.videoplayer.nativeElement;
    media.muted = true; // without this line it's not working although I have "muted" in HTML
    media.play();
}

回答by u10971754

Try to use mousemove event lisentner

尝试使用 mousemove 事件监听器

var audio = document.createElement("AUDIO")
document.body.appendChild(audio);
audio.src = "./audio/rain.m4a"

document.body.addEventListener("mousemove", function () {
    audio.play()
})

回答by IVO GELOV

NOT WORKING ANY MORE

不再工作



UPDATE

更新

If this technique does not work any more - there is another option. You can include a short and very quiet (-60db) audio and play it inside the click handler of the hidden button. After that, all other audio/video files will be allowed to play without a direct user interaction. You can take a silent audio from http://adventure.land/sounds/loops/empty_loop_for_js_performance.wavand cut it to half a second (or less).

如果这种技术不再起作用 - 还有另一种选择。您可以包含一个简短且非常安静 (-60db) 的音频并在隐藏按钮的点击处理程序中播放它。之后,所有其他音频/视频文件将无需直接用户交互即可播放。您可以从http://adventure.land/sounds/loops/empty_loop_for_js_performance.wav获取无声音频并将其缩短为半秒(或更短)。



There is a very easy solution - just add a BUTTON to your page, style it to be invisible and then call button.click()method before the play()

有一个非常简单的解决方案 - 只需在您的页面中添加一个 BUTTON,将其设置为不可见,然后button.click()play()

Runs like a charm in Chromium Version 70.0.3538.67 (Official Build) (64-bit)

在 Chromium 版本 70.0.3538.67(官方版本)(64 位)中运行起来就像一个魅力

var btn = document.getElementById('btn');
document.addEventListener(btn,myPlay,false);
btn.click();

function myPlay()
{
  document.getElementById('movie').play();
}
<video
    title="Advertisement" id="movie"
    style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
    src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm"
    ></video>
    <button type="button" style="z-index:-1;opacity:0;position: absolute;left:-1000px;" id="btn"></button>

回答by Shobi

In my case, I had to do this

就我而言,我必须这样做

 // Initialization in the dom
 // Consider the muted attribute
 <audio id="notification" src="path/to/sound.mp3" muted></audio>


 // in the js code unmute the audio once the event happened
 document.getElementById('notification').muted = false;
 document.getElementById('notification').play();

回答by Bernesto

Extend the DOM Element, Handle the Error, and Degrade Gracefully

扩展DOM元素,处理错误,优雅降级

Below I use the prototype function to wrap the native DOM play function, grab its promise, and then degrade to a play button if the browser throws an exception. This extension addresses the shortcoming of the browser and is plug-n-play in any page with knowledge of the target element(s).

下面我使用prototype函数来包装原生DOM播放函数,抓取它的promise,然后如果浏览器抛出异常就降级为一个播放按钮。此扩展解决了浏览器的缺点,并且可以在任何具有目标元素知识的页面中即插即用。

// 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>

回答by Alarik

Chrome needs a user interaction for the video to be autoplayed or played via js (video.play()). But the interaction can be of any kind, in any moment. If you just click random on the page, the video will autoplay. I resolved then, adding a button (only on chrome browsers) that says "enable video autoplay". The button does nothing, but just clicking it, is the required user interaction for any further video.

Chrome 需要用户交互才能自动播放或通过 js (video.play()) 播放视频。但是交互可以是任何类型的,在任何时候。如果您只是在页面上单击随机,视频将自动播放。然后我解决了,添加了一个按钮(仅在 chrome 浏览器上),上面写着“启用视频自动播放”。该按钮什么都不做,只是点击它,是任何进一步视频所需的用户交互。