简体   繁体   English

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

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

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() failed 因为用户没有先与文档交互。

..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?那么绕过 Chrome v66 的自动播放拦截器真的像在<video>元素中添加webkit-playsinline="true"playsinline="true"autoplay=""属性一样简单吗? Are there any negative consequences to this?这有什么负面影响吗?

To make the autoplay on html 5 elements work after the chrome 66 update you just need to add the muted property to the video element.要在 chrome 66 更新后使 html 5 元素上的自动播放工作,您只需将muted属性添加到 video 元素。

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.我相信 chrome 66 更新试图阻止标签在用户标签上产生随机噪音。 That's why the muted property make the autoplay work again.这就是为什么 muted 属性使自动播放再次起作用的原因。

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();
}

Try to use mousemove event listener尝试使用 mousemove 事件监听器

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

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

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>

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 snippet button, 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 有比这更严格的规则,并且要求您至少在用户事件处理程序本身的<video><audio>元素上以编程方式实际触发一次play()方法。

 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.如果你不需要音频,那就不要把它附加到你的媒体上,只有一个视频轨道的视频也可以自动播放,这会减少用户的带宽使用。

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.下面我使用原型函数来包装原生的 DOM 播放函数,抓取它的 Promise,然后如果浏览器抛出异常就降级为播放按钮。 This extension addresses the shortcoming of the browser and is plug-n-play in any page with knowledge of the target element(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>

According to the new browser policy, the user must interact with DOM first before playing the Audio element.根据新的浏览器策略,用户必须先与 DOM 交互,然后才能播放 Audio 元素。

If you want to play the media on page load then you can simply add autoplay property to audio element in HTML like this如果您想在页面加载时播放媒体,那么您可以像这样简单地将自动播放属性添加到 HTML 中的音频元素

<video id="video" src="./music.mp4" autoplay>

or if you don't want to do autoplay then you can handle this using Javascript.或者如果您不想进行自动播放,那么您可以使用 Javascript 来处理。 Since the autoplay property is set to true, media will be played, we can simply mute the media.由于 autoplay 属性设置为 true,将播放媒体,我们可以简单地将媒体静音。

document.getElementById('video').autoplay = true;
document.getElementById('video').muted = true; 

Imp: Now Whenever you play the media don't forget to turn the muted property to false. Imp:现在,无论何时播放媒体,都不要忘记将 muted 属性设置为 false。 Like this像这样

document.getElementById('video').muted = false; 
document.getElementById('video').play();

Or you can also show a simple popup where the user will click the allow button in the modal.或者您也可以显示一个简单的弹出窗口,用户将在其中单击模式中的允许按钮。 So he interacts with DOM first, then you don't need anything to do所以他先和DOM交互,然后你什么都不需要做

I got this error我收到了这个错误

Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. Uncaught (in promise) DOMException: play() failed 因为用户没有先与文档交互。

And here's what I did in my Angular Project这就是我在 Angular 项目中所做的

Key Point: Don't ever assume a video will play, and don't show a pause button when the video is not actually playing.关键点:永远不要假设视频会播放,也不要在视频未实际播放时显示暂停按钮。

You should always look at the Promise returned by the play function to see if it was rejected:您应该始终查看 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();
        });
    }
}

Source: Autoplay policy资料来源: 自动播放政策

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();

I had a similar problem, I need to play the video without muting it.我有类似的问题,我需要播放视频而不静音。 The way i did this, wait for a second then triggered the event by button.我这样做的方式,等待一秒钟然后通过按钮触发事件。 Here is my code这是我的代码

if (playVideo == '1') {
    setTimeout(function() {
        $("#watch_video_btn").trigger('click');
    }, 1000);
}

UPDATE 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. 您可以包含一个简短且非常安静(-60db)的音频,并在隐藏按钮的单击处理程序中播放。 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.wav and cut it to half a second (or less). 您可以从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,将其设置为不可见,然后在play()之前调用button.click()方法

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> 

Chrome needs a user interaction for the video to be autoplayed or played via js (video.play()). Chrome 需要用户交互才能自动播放或通过 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".然后我解决了,添加了一个按钮(仅在 chrome 浏览器上),上面写着“启用视频自动播放”。 The button does nothing, but just clicking it, is the required user interaction for any further video.该按钮什么也不做,只是单击它,是任何进一步视频所需的用户交互。

I changed my UI to have the user press a button to load the website (and when the website loads after they click the button, the audio plays)我更改了我的用户界面,让用户按下按钮来加载网站(当他们点击按钮后网站加载时,音频播放)

Since they interact with the DOM, then the audio plays!!!因为它们与 DOM 交互,所以音频播放!!!

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

I had some issues playing on Android Phone.我在 Android 手机上玩游戏时遇到了一些问题。 After few tries I found out that when Data Saver is on there is no auto play:经过几次尝试,我发现当数据保护程序打开时没有自动播放:

There is no autoplay if Data Saver mode is enabled.如果启用Data Saver模式,则不会自动播放。 If Data Saver mode is enabled, autoplay is disabled in Media settings.如果启用流量节省模式,则在媒体设置中禁用自动播放。

Source 资源

I encountered a similar error with while attempting to play an audio file.我在尝试播放音频文件时遇到了类似的错误。 At first, it was working, then it stopped working when I started using ChangeDetector's markForCheck method in the same function to trigger a re-render when a promise resolves (I had an issue with view rendering).起初,它正在工作,然后当我开始在同一个函数中使用 ChangeDetector 的markForCheck方法以在承诺解决时触发重新渲染时它停止工作(我遇到了视图渲染问题)。

When I changed the markForCheck to detectChanges it started working again.当我将markForCheck更改为detectChanges时,它又开始工作了。 I really can't explain what happened, I just thought of dropping this here, perhaps it would help someone.我真的无法解释发生了什么,我只是想把它放在这里,也许它会对某人有所帮助。

You should have added muted attribute inside your videoElement for your code work as expected.您应该在videoElement中添加muted属性,以便您的代码按预期工作。 Look bellow ..看下面..

<video id="IPcamerastream" muted="muted" autoplay src="videoplayback%20(1).mp4" width="960" height="540"></video>

Don' t forget to add a valid video link as source不要忘记添加有效的视频链接作为源

音频自动播放属性在 MS Edge 中不起作用

Type Chrome://flags in the address-bar在地址栏中输入Chrome://flags

Search: Autoplay搜索:自动播放

Autoplay Policy自动播放政策

Policy used when deciding if audio or video is allowed to autoplay.决定是否允许自动播放音频或视频时使用的策略。

– Mac, Windows, Linux, Chrome OS, Android – Mac、Windows、Linux、Chrome 操作系统、Android

Set this to " No user gesture is required "将此设置为“不需要用户手势

Relaunch Chrome and you don't have to change any code重新启动 Chrome,您无需更改任何代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何处理“未捕获(承诺)DOMException:play() 失败,因为用户没有先与文档交互。”? - How to handle “Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.”? 出现错误 - Uncaught (in promise) DOMException: play() failed 因为用户没有先与文档交互 - getting error - Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first Uncaught (in promise) DOMException: play() 失败,因为用户没有先与文档交互 - Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first Uncaught (in promise): DOMException: play() failed 因为用户没有首先在控制台中与文档交互 - Uncaught (in promise) : DOMException: play() failed because the user didn't interact with the document first in console 解决 Uncaught (in promise) DOMException: play() failed 因为用户没有先与文档交互 - Solve Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first Error Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first,我该如何解决这个问题? - Error Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first, how can i solve this? 在交叉路口播放/暂停带声音的视频 - Chrome - DOMException: play() 失败,因为用户没有先与文档交互 - Play/Pause video with sound on intersection - Chrome - DOMException: play() failed because the user didn't interact with the document first 静音的自动播放视频显示错误:play()失败,因为用户没有首先与文档进行交互。 - Muted Autoplay video shows error: play() failed because the user didn't interact with the document first. play() 失败,因为用户没有与文档第一次交互 - play() failed because the user didn't interact with the document first issue Android 7 Chrome - play() 失败,因为用户没有先与文档交互 - Android 7 Chrome - play() failed because the user didn't interact with the document first
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM