草庐IT

HTML页面激活态:为何音频无法自动播放?

水鱼兄 2023-12-10 原文

本文为HTML标准解读系列文章,其他文章详见这里

你可能也遇到过,页面内的video/audio标签无法自动播放的问题:

<video src="./test.mp4" autoplay></video>

这时如果你添加muted属性,他就能自动播放了,虽然是在没有声音的情况下:

<video src="./test.mp4" autoplay muted></video>

这其实是浏览器的防骚扰机制:只有在用户至少与页面交互过一次的情况下,浏览器才允许页面放出声音。

而声音限制只是这个防骚扰机制的其中一部分内容,一些浏览器API也受到同样的约束,只有在页面曾经被激活过的情况才能使用。还有一些API,有着更加严格的要求,必须是用户正在与页面进行积极的交互才能触发。具体是哪些API,我们会在下面提到,不过在此之前,让我们先来看看HTML的页面激活机制。

HTML页面激活机制

HTML页面可以有两种激活状态:

  • 粘性激活态(Sticky activation):只要用户与页面交互过一次,页面就会一直处于这个状态,这个状态可以判断用户是否曾经与页面有过交互。
  • 短暂激活态(Transient activation):用户与页面的每次交互,都会让页面处于这个状态。但这个状态是有“有效期”的,如果在交互后的一段时间内,用户没有再与页面进行交互,这个状态就会过期。具体的有效期时长由浏览器决定,比如chrome是5秒。

那么,怎么样才算用户与页面“进行了一次交互”呢??标准答案是:当页面触发了以下事件,且事件的isTrusted属性值为true时:

  • keydown,且不是ESC 键以及不是浏览器使用的其他快捷键;
  • mousedown
  • pointerdown,且pointerType属性是"mouse";
  • pointerup,且pointerType属性不是"mouse";
  • touchend

可以看出,这里的一些条件,是防止开发者通过脚本伪造真实用户行为来激活页面的。比如对于isTrusted属性值的要求:isTrusted是一个只读的属性,由脚本创建的事件,其值为false,只有由用户真实动作触发的事件,其值才为true。

查看页面激活状态

有两个API可以查看页面的激活状态:

  • navigator.userActivation.hasBeenActive:查看页面是否处于粘性激活态。
  • navigator.userActivation.isActive:查看页面是否处于短暂激活态。

于是,通过检测页面激活状态,我们可以使视频带有声音地自动播放。在以下的代码中,我使用脏检查,当用户第一次激活页面的时候,就会给页面插入一个视频并自动播放:

<script>
    const t = setInterval(() => {
            if (navigator.userActivation.hasBeenActive){
                // 页面进入粘性激活态
                const v = document.createElement('video')
                v.src = './test.mp4'
                v.autoplay = true
                document.body.appendChild(v)
                clearInterval(t)
            }
        }, 1000);
</script>

遗憾的是,虽然这两个API已经写进了标准,但是目前safari以及firefox并不支持这两个API。

受页面激活态限制的浏览器API

所有受到页面激活态限制的API,可以分为三个类别:

  • 粘性激活态-限制API(Sticky activation-gated APIs) :页面必须处于粘性激活态才能使用的API。如:
  • 短暂激活态-限制API(Transient activation-gated APIs) :页面必须处于短暂激活态才能使用的API。如:
    • 当iframe的sandbox属性声明allow-top-navigation-by-user-activation关键词时,尝试在iframe外的浏览上下文中导航。
    • 对于type=filetype=color的input元素,使用input.showPicker()的方法。
    • 剪切板Clipboard相关API。
  • 短暂激活态-销毁API(Transient activation-consuming APIs) :页面必须处于短暂激活态才能使用的API,但每一次使用后都会促使页面短暂激活态过期,以此来避免重复调用API。换句话说,每一次用户交互,这类API最多只能被调用一次。
    • window.open()方法。

HTML标准并没有对受页面激活态限制的API进行一个完整的总结,它们大部分散落在不同的web标准/草案中,所以我在这里只能列举一些常用的API。其他更多的API,也可以查看MDN这篇文档

有关HTML页面激活态:为何音频无法自动播放?的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  8. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  9. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  10. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

随机推荐