如何处理 Chrome 66 桌面上的“Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document”?

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

提问人:Steven 提问时间:4/20/2018 更新时间:7/2/2023 访问量:520749

问:

我收到错误消息。.

未捕获(承诺中) 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>

JavaScript 谷歌-Chrome HTML5-视频

评论

2赞 Josh Lee 4/20/2018
我认为 playsinline 是 iOS 的东西。
5赞 nbar 8/27/2021
@everyone:youtube 如何绕过“无用户互动”规则?
2赞 Carson 1/20/2022
此链接可能会有所帮助 developer.chrome.com/blog/autoplay

答:

16赞 Kaiido 4/20/2018 #1

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

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

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

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

在第一次加载时,如果你不点击任何位置,它就不会运行,因为我们还没有注册任何事件。
但是,一旦单击“运行”按钮,父文档(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 的规则比这更严格,并且要求您至少以编程方式在用户事件处理程序本身的 or 元素上实际触发一次该方法。play()<video><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>

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

评论

1赞 Kaiido 8/27/2020
@JanTuroň不,你不能。 并且方法需要直接从 HTMLMediaElement 实例中调用,或者需要创建方法的绑定副本,例如 ,这并不比简单的 ..play.pausevid.play.then(vid.pause.bind(vid))vid.play.then(()=>vid.pause())
0赞 Ajeet Eppakayala 4/13/2022
你能检查一下事情是否像你说的那样吗?我正在使用 chrome,但正如您所说,没有任何效果。对于小提琴,我必须在 Iframe 内部单击(不在视频上),然后“运行”才能播放视频。而且片段也不起作用。
-7赞 DARKSETH23 4/20/2018 #2

在地址栏中键入 Chrome://flags

搜索:自动播放

自动播放策略

决定是否允许音频或视频时使用的策略 自动播放。

– Mac、Windows、Linux、Chrome OS、Android

将此设置为“不需要用户手势"

重新启动 Chrome,您无需更改任何代码

评论

35赞 DesTroy 5/14/2018
您不可能要求每个用户都更改设置。
2赞 Milan Švehla 8/20/2019
这实际上可以解决某些人的问题(信息亭、私人和本地网站......现在唯一的解决方案就是这个答案
0赞 vdegenne 1/16/2023
@DesTroy你的评论没有意义。如果 Chrome 不允许您在用户最初请求/允许的情况下自动播放视频/音频,这是有充分理由的!原因很简单,允许每个用户这样做是一个坏主意(这会让恶意的人利用它来发挥自己的优势并在页面加载时播放一些东西,这很快就会让每个人都感到烦恼)。那么是的,如果你真的想激活这个功能,它只是为了你自己,因此必须更深入地激活一个标志。那个家伙的解决方案是合法的。
1赞 Ming 5/7/2018 #3
  1. 打开chrome://settings/content/sound
  2. 设置 不需要用户手势
  3. 重新启动 Chrome

评论

6赞 Ming 5/10/2018
自动播放策略更改。点击我
5赞 Tuan Nguyen 5/21/2018
它仅供开发人员在本地测试 Chrome 自动播放策略行为。developers.google.com/web/updates/2017/09/......
11赞 nickiaconis 6/12/2018
我发现命令行标志是实现此设置的编程方式。--autoplay-policy=no-user-gesture-required
54赞 koosa 10/9/2018
这仅适用于您的浏览器,其他人仍然会受到影响
94赞 adripanico 2/1/2019
谁在为这个答案投赞成票?这不是 superuser.com。本地计算机的解决方案不能是一个可接受的答案。
255赞 Joe 6/7/2018 #4

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

所以你当前的视频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>

只是需要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>

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

评论

2赞 nikitahl 2/8/2019
有没有办法在视频开始播放后立即启用音频?删除属性或设置属性无济于事。mutevolume
6赞 tgordon18 3/31/2020
我不得不这样做muted="true"
1赞 Panagiss 5/27/2020
最好将 OR 设置为muted=truemuted=false
4赞 Black 12/10/2020
你也可以至少为我写作品。muted
12赞 Gamer In The Game 7/28/2021
我在<audio>元素上遇到了这个问题,我该如何解决?
17赞 Moiz 6/18/2018 #5

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

[HTML全文]

<video loop muted autoplay id="videomain">
  <source src="videoname.mp4" type="video/mp4">
</video>
1赞 Ido 1/21/2019 #6

我在 Android 手机上玩时遇到了一些问题。 经过几次尝试,我发现当流量节省程序打开时,没有自动播放:

如果启用了流量节省模式,则不会自动播放。如果启用了节约模式,则在媒体设置中禁用自动播放。

28赞 時雨初 1/26/2019 #7

尝试使用 mousemove 事件侦听器

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

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

评论

4赞 maryisdead 5/5/2022
在 Chrome 中不再起作用(针对版本 100.0.4896.127 测试)。编辑:鼠标移动在执行一次单击起作用。
3赞 55 Cancri 9/19/2022
这个答案让我疯狂地骑行
2赞 Alarik 3/10/2019 #8

Chrome 需要用户交互才能自动播放视频或通过 js (video.play()) 播放。 但互动可以是任何类型的,在任何时刻。 如果您只是在页面上随机单击,视频将自动播放。 然后我下定决心,添加一个按钮(仅在 chrome 浏览器上),上面写着“启用视频自动播放”。该按钮不执行任何操作,但只需单击它,即可进行任何后续视频所需的用户交互。

73赞 Eutrepe 3/21/2019 #9

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

在 HTML 中,您应该添加autoplay muted

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

评论

1赞 Pedro Ferreira 10/22/2019
绝对真实且难以置信,即使使用最新的 Angular 版本 Ng8。Angular 根本不关心组件的 HTML 模板上发生了什么!
2赞 Pedro Ferreira 10/22/2019
而且,使用新的 Angular 的使用方式,您需要将 sttatic option 设置为 true: 然后:@ViewChild()@ViewChild('videoPlayer', {static: true}) videoplayer: ElementRef;video: HTMLVideoElement;this.video = this.videoplayer.nativeElement; @ ngOnInit()
2赞 Ignacio Bustos 1/4/2020
这是我的问题,HTML 中的静音被完全忽略,我不得不通过 JS 强制它。+ 1M 经过几天的搜索到您的答案
2赞 arao6 6/10/2020
哇,简直不敢相信我真的需要 javascript 端静音来用于 Angular SSR 加载后视图。一直以来,我都认为HTML是问题所在。
0赞 akaravashkin 2/15/2022
这是唯一的正确答案!谢谢你,帮了我很多。
1赞 King 5/19/2019 #10

我在尝试播放音频文件时遇到了类似的错误。起初,它正在工作,然后当我开始在同一函数中使用 ChangeDetector 的方法在承诺解析时触发重新渲染时它停止工作(我在视图渲染方面遇到了问题)。markForCheck

当我更改为它时,它又开始工作了。我真的无法解释发生了什么,我只是想把这个放在这里,也许它会帮助某人。markForCheckdetectChanges

17赞 Bernesto 5/24/2019 #11

扩展 DOM 元素,处理错误,并正常降级

下面我使用 prototype 函数来包装原生的 DOM play 函数,抓住它的承诺,然后在浏览器抛出异常时降级为播放按钮。此扩展解决了浏览器的缺点,并且可以在任何了解目标元素的页面中即插即用。

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

评论

1赞 loretoparisi 6/26/2020
这是一种非常聪明的方法,它不会破坏任何策略(因为无论如何都不会开始播放),并防止出现错误。+1
0赞 TefoD 8/1/2021
迪托。防止错误和任何策略也是我的目标。任何声音都可以等到用户互动 - 太棒了!
1赞 GNETO DOMINIQUE 6/3/2019 #12

您应该在 your 中添加属性,以便代码按预期工作。看下面..mutedvideoElement

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

不要忘记添加有效的视频链接作为源

10赞 Shobi 12/23/2019 #13

就我而言,我必须这样做

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

评论

4赞 Arg 10/19/2020
Não funciona testei no chrome Uncaught (in promise) DOMException: play() 失败,因为用户没有先与文档交互
9赞 pranav shinde 11/2/2020 #14

根据新的浏览器策略,用户必须先与 DOM 交互,然后才能播放 Audio 元素。

如果你想在页面加载时播放媒体,那么你可以简单地将autoplay属性添加到HTML中的音频元素,如下所示

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

或者如果你不想做自动播放,那么你可以使用 Javascript 来处理这个问题。由于 autoplay 属性设置为 true,因此将播放媒体,我们只需将媒体静音即可。

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

Imp:现在,每当您播放媒体时,请不要忘记将 muted 属性设置为 false。喜欢这个

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

或者,您也可以显示一个简单的弹出窗口,用户将在其中单击模式中的允许按钮。所以他先和 DOM 交互,然后你就不需要做任何事情了

21赞 jna 6/25/2021 #15

我收到此错误

未捕获(承诺中) 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();
        });
    }
}

来源:自动播放政策

评论

2赞 RomanistHere 4/22/2023
优雅的解决方案,非常好!
2赞 Panama Jack 10/5/2023
这是正确答案,因为它实际上处理了未捕获的异常。是的,添加静音可以修复它,但您仍然应该提供错误处理,然后解决是否播放它。
4赞 Alauddin Ahmed 8/14/2021 #16

我遇到了类似的问题,我需要在不静音的情况下播放视频。我这样做的方式是等待一秒钟,然后通过按钮触发事件。这是我的代码

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

评论

0赞 deFreitas 1/24/2023
没用......
-2赞 Bahaa Salaheldin 3/21/2022 #17

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

3赞 Jesus is Lord 4/8/2022 #18

我更改了我的 UI,让用户按下按钮来加载网站(当他们单击按钮后加载网站时,会播放音频)

由于它们与 DOM 交互,因此音频会播放!!

评论

1赞 deFreitas 1/24/2023
悲伤的故事,这里也一样......
1赞 Mustafa 5/26/2023
很酷的主意耶稣
4赞 Yan King Yin 11/9/2022 #19

就我而言,它只是在开始时自动调用的咔哒声(我不介意它是否静音)。所以我使用:

const clickSound = new Audio('click.wav');
clickSound.play().catch(function (error) {
    console.log("Chrome cannot play sound without user interaction first")});

以消除错误。

0赞 丶 Limeー来夢 丶 7/2/2023 #20

有一些编程解决方案可以绕过该功能。

一些例子是使用 Java 的 Robot 或 Autohotkey,作为 Chrome 层之上的另一种解决方案。但是 IMO 它不是很聪明。因此,我最喜欢的解决方法(虽然有点棘手)是使用 Chrome 扩展 API 中的 API。chrome.debuggerInput.dispatchMouseEvent

var __target = 1857385916; // -- replace here with the tab id you desire

var x = 360 // -- replace here with your desired position to emulate click
var y = 360 // -- here as well
var button = "right"
var clickCount = 1

chrome.debugger.sendCommand({ tabId: __target }, 'Input.dispatchMouseEvent', {
    type: 'mousePressed',
    x: x,
    y: y,
    button: button,
    clickCount: clickCount,
}, () => {
  chrome.debugger.sendCommand({ tabId: __target }, 'Input.dispatchMouseEvent', {
    type: 'mouseReleased',
    x: x,
    y: y,
    button: button,
    clickCount: clickCount,
  })
});

初学者注意事项:

创建一个Chrome扩展程序,其中background.js创建为上述脚本,manifest.json当然是在启用权限的情况下创建的。debugger

Chrome的菜单->“管理扩展程序”->启用“开发者模式”->“加载解压缩”以像往常一样加载扩展程序。

您可能想知道要模拟鼠标事件的所需选项卡的选项卡 ID。我制作的以下脚本可能有助于快速识别每个选项卡的 ID。

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status === "complete" && tab.active && tab.url) {
        var obj = {
            tabId: tabId,
            title: tab.title,
            url: tab.url,
        }
        console.log("[(background) tab id logger]", obj, );
    }
});

在manifest.json中添加“tabs”权限,重新加载扩展,点击“后台页面”打开后台脚本检查窗口,将上面的JavaScript脚本粘贴到控制台上运行脚本。如果您没有看到任何错误,请重新加载任何选项卡,您将很快看到控制台上记录的选项卡 ID。