如何处理"Uncaught(in promise)DOMException:play()失败,因为用户没有先与文档交互." 在桌面上使用Chrome 66?

Ste*_*ven 83 javascript video google-chrome html5-video

我收到错误消息..

未捕获(在promise中)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>
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*Joe 94

要在chrome 66更新后使html 5标签上的自动播放工作,您只需将该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>
Run Code Online (Sandbox Code Playgroud)

只是需要 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>
Run Code Online (Sandbox Code Playgroud)

我相信chrome 66更新试图阻止标签在用户标签上创建随机噪音.这就是为什么静音属性使自动播放再次起作用的原因.

  • 我遇到 &lt;audio&gt; 元素的问题,如何解决? (12认同)
  • 我必须改为`muted =“true”` (5认同)
  • 拉出我的头发一个小时后。这解决了我的问题 (2认同)
  • 有没有办法在视频开始播放后立即启用音频?删除“静音”属性或设置“音量”属性没有帮助。 (2认同)
  • 你也可以只写“静音”,至少对我来说是这样。 (2认同)

Min*_*ing 25

  1. 打开 chrome://flags/#autoplay-policy
  2. 设置无用户手势是必需的
  3. 重新启动Chrome

  • 这仅适用于您的浏览器,其他人仍然会受到影响 (14认同)
  • 谁在支持这个答案?这不是superuser.com。不能为您的本地计算机提供解决方案。 (8认同)
  • 自动播放政策更改.[点击我](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes) (5认同)
  • 可能这并不完全是OP想要的,但这可以解决我的问题,因为在我们的例子中,浏览器处于Kiosk模式,我们将管理浏览器 - 所以感谢这一点。 (5认同)
  • 它仅用于开发人员在本地测试Chrome自动播放策略行为.https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#developer-switches (4认同)
  • 我发现命令行标志`--autoplay-policy = no-user-gesture-required`是实现此设置的编程方式. (3认同)
  • 有没有一种程序化的方法来实现这一目标?我在无头Chrome中运行自动化测试,由于此策略现在失败了.我试过通过Testem传递几个不同的命令行标志无济于事. (2认同)

jna*_*jna 21

我收到这个错误

未捕获(承诺中)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();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

来源:自动播放政策

  • 优雅的解决方案,非常好! (2认同)
  • 这是正确的答案,因为它实际上处理了未捕获的异常。是的,添加静音可以修复它,但您仍然应该提供错误处理,然后解决播放或不播放的问题。 (2认同)

Moi*_*oiz 13

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

HTML

<video loop muted autoplay id="videomain">
  <source src="videoname.mp4" type="video/mp4">
</video>
Run Code Online (Sandbox Code Playgroud)


Kai*_*ido 10

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

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

所以就拿这个小提琴,这是唯一

<video src="myvidwithsound.webm" autoplay=""></video>
Run Code Online (Sandbox Code Playgroud)

在第一次加载时,如果你没有点击任何地方,它将无法运行,因为我们还没有注册任何事件.
但是一旦你点击"运行"按钮,那么父文档(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>
Run Code Online (Sandbox Code Playgroud)

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


现在,请注意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);
};
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

如果您不需要音频,那么只需将其连接到您的媒体,只允许视频轨道的视频也可以自动播放,并且会降低用户的带宽使用率.


Ber*_*sto 8

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

下面我使用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>
Run Code Online (Sandbox Code Playgroud)


小智 7

尝试使用mousemove事件lisentner

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

document.body.addEventListener("mousemove", function () {
    audio.play()
})
Run Code Online (Sandbox Code Playgroud)

  • 在 Chrome 中不再起作用(针对版本 100.0.4896.127 进行测试)。编辑:鼠标移动在执行一次单击后起作用。 (5认同)
  • 这个答案让我经历了一次疯狂的旅程 (3认同)

Eut*_*epe 6

对我来说(在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();
}
Run Code Online (Sandbox Code Playgroud)

  • 并且,使用新的 Angular 使用 `@ViewChild()` 的方式,您需要将 static 选项设置为 true: `@ViewChild('videoPlayer', {static: true}) videoplayer: ElementRef;` `video: HTMLVideoElement;` 并且然后: `this.video = this.videoplayer.nativeElement;` @ `ngOnInit()` (2认同)
  • 这是我的问题,HTML 中的静音被完全忽略,我不得不通过 JS 强制它。经过几天的搜索后,您的答案增加了 100 万 (2认同)
  • 哇,不敢相信我实际上需要 Angular SSR 加载后视图的 javascript 端静音。一直以来,我都认为 HTML 是问题所在。 (2认同)

pra*_*nde 6

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

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

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

或者,如果您不想进行自动播放,则可以使用 Javascript 来处理此问题。由于 autoplay 属性设置为 true,媒体将被播放,我们可以简单地将媒体静音。

document.getElementById('video').autoplay = true;
document.getElementById('video').muted = true; 
Run Code Online (Sandbox Code Playgroud)

Imp:现在每当您播放媒体时,请不要忘记将静音属性设置为 false。像这样

document.getElementById('video').muted = false; 
document.getElementById('video').play();
Run Code Online (Sandbox Code Playgroud)

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


Sho*_*obi 5

就我而言,我必须这样做

 // 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();
Run Code Online (Sandbox Code Playgroud)

  • Não funciona testei no chrome Uncaught (in Promise) DOMException: play() 失败,因为用户没有首先与文档交互 (4认同)