【问题标题】:Browser denying javascript play()浏览器拒绝 javascript play()
【发布时间】:2019-12-21 13:37:10
【问题描述】:

我有一个带有用于扫描产品的输入字段的页面。当扫描条形码或在字段中输入 SKU 时,会发出 ajax 请求,应用程序会根据使用 HTMLMediaElement.play() 的响应播放成功或错误声音。

sounds.error.play();

这在前一段时间工作正常,但现在我收到此错误:

⚠ 只有在用户批准、用户激活网站或媒体静音时才允许自动播放。

接着是:

NotAllowedError:当前上下文中用户代理或平台不允许播放方法,可能是因为用户拒绝了权限。

由于此页面仅用于扫描 SKU,因此当页面加载时,该输入字段会以编程方式聚焦,以便最终用户更轻松地进行操作。我尝试删除此焦点,以便用户必须单击输入字段,但这似乎不满足允许播放音频的任何要求

经过更多试验后,我发现通过一些额外的用户交互,声音会播放。例如,如果我创建一个复选框来“启用”声音并且用户单击它,这似乎就足够了。或者,如果用户在输入元素之外单击,然后再次返回,这也可以。

满足大多数现代浏览器以允许播放音频的确切要求是什么?

我意识到对于不同的浏览器和配置,答案可能会有所不同,但我无法为当前版本的 Firefox 或 Chrome 找到任何权威。我正在寻找一种解决方法,以便应用程序不需要因额外的点击或其他类型的交互而变得复杂,并且由于我现在知道这项新政策,我希望修订尽可能不引人注目。

更新:

这是我为演示该问题而设计的一个基本示例。我刚才尝试了三种不同的浏览器,它们的行为都有些不同。特别是 Firefox 的行为如上所述 - 直到我关注输入字段,模糊,然后再次单击以聚焦时才会播放声音:

http://so.dev.zuma-design.com/input-sounds.html

【问题讨论】:

  • 查看最近的autoplay policy announcement。这取决于网站的 ME 指数。至少,有 canplay js 库来检查是否可以自动播放。
  • @bigless - 我在谷歌上搜索了“canplay js”,但一无所获。你能给我一个链接吗?如果不尝试播放并捕捉到 promise 错误,我就无法做出这个决定——这需要我先尝试播放声音。
  • 对不起。它是can-autoplay

标签: javascript google-chrome firefox audio


【解决方案1】:

在 Safari 中允许在 video 标签中自动播放,您需要向它们添加 playsinline 属性。像这样:

<video autoplay="" muted="" playsinline=""></video>

【讨论】:

  • 这是为我做的!非常感谢
【解决方案2】:

我也遇到了同样的问题,而且我很容易就解决了这个问题:

只需在播放按钮上更改事件监听器

onClick={togglePlay}onClickCapture={togglePlay}

React 中使用钩子的示例:

const Player = ({ audio }) => {
const [playing, setPlaying] = useState(false);

const togglePlaying = () => setPlaying((prev) => !prev);

useEffect(() => {
    if (audioRef && audioRef.current) {
        if (playing) {
            audioRef.current.play();
        } else {
            audioRef.current.pause();
        }
    }
  }, [playing]);

  return (

 <audio
            
            autoPlay=""
            src={audio}
            ref={audioRef}
            onTimeUpdate={(e) => setCurrentTime(e.target.currentTime)}
            onCanPlay={(e) => setDur(e.target.duration)}
            onEnded={songEnded}
        />
            <PlayerStart onClickCapture={togglePlaying}>
                    {playing ? <PauseIcon /> : <PlayIcon />}
            </PlayerStart>
    )
}

【讨论】:

  • onClickCapture={togglePlay} 为我做了。老实说,这种奇怪的行为看起来像是一个 safari bug,因为我没有自动播放,而且用户已经与网站进行了交互。
【解决方案3】:

[编辑] Firefox 70 fixes this issue。该答案的其余部分提供了解释和建议的解决方法。

正如您 wondered 所说,“用户已与网站互动” 标准具体意味着什么:

一个想法 - 从一个假的/模糊的文本框开始,并在输入第一个字符后显示/聚焦真实的文本框(通过 JS 将第一个字符添加到文本输入中) - 以下代码似乎在 Firefox 中工作:

$(document).one('keypress', function(ev) {
    // copy the first character typed over to the text input
    let char = String.fromCharCode(ev.which);
    $('.play').val(char).focus();
});

$('.play').on('keypress', function() {
    if($(this).val().length === 3) { // assuming you want to validate when a certain number of characters is typed
        sounds[$(this).data('sound')].play();
    }
})

如果用户通过单击文本输入开始,这将无济于事,但可以针对这种情况实施回退的无声反馈。

【讨论】:

  • 感谢您在这里阐明一些关键点。我仍然觉得标准有点模棱两可,导致我正在经历那种不一致的行为。虽然这样的事情通常对 Web 浏览体验有好处,但对于像我这样开发不适合公众的私有 Web 应用程序的人来说,它们是一个祸根。我们喜欢旧的行为,现在员工不得不无缘无故地进行额外的点击。我想要一个让我到达那里的解决方法......还有一个问题 - 你能在最后解释一下你的想法吗?我不明白会/可能/可能会如何提供帮助。
  • 1) 内部网络应用程序和互联网网站是不同的;您的问题集中在网络行为上,如果您控制客户端,则可以覆盖该行为,内部应用程序通常就是这种情况。 2)由于文本框外的按键应该“激活”网页并允许它稍后播放音频,因此想法是使用户的第一次按键发生在文本框外并将其转发到 JS 处理程序中的输入.我在答案中添加了一些代码。
  • 我还注意到我弄乱了我对 Firefox 中使用的标准的描述,这可能使我的回答变得混乱。现已修复。
  • 我仍然完全不知道为什么它有效,但它确实有效。检查我创建的两个新示例,它们尝试在由用户点击“返回或输入”触发的模糊事件上播放声音:so.dev.zuma-design.com/input-sounds-b.html 不起作用。在这一个中,我将输入字段自动聚焦在页面加载上。你输入一些东西并按回车键,应该会播放声音。但它没有
  • 我也不明白这些规则背后的动机。我asked in the bug where this was implemented.
【解决方案4】:

当归结为自动播放多媒体时,所有现代浏览器(尤其是 chrome)都存在一些权限阻塞。

这是来自MDN 的自动播放可用性部分,它显示了何时允许媒体自动执行:

  • 音频已静音或音量设置为 0;
  • 用户与网站进行了交互(通过单击、点击、 按键等)
  • 如果网站已被列入白名单;这可能会发生 如果浏览器确定用户参与,则自动 经常使用媒体,或通过首选项或其他用户手动 界面功能
  • 如果使用自动播放功能策略授予 对&lt;iframe&gt; 及其文档的自动播放支持。

这是与arrayBuffer using AJAX 类似的解决方案

这是DEMO

【讨论】:

  • "用户与网站进行了交互" - 这部分是我正在努力解决的问题。因为正如我所说,仅仅单击该字段似乎是不够的。我至少必须点击退出然后再次进入它,因此 MDN 上的声明是模棱两可的,因为似乎有一个交互阈值,我正在寻找关于该阈值到底是什么的明确性。跨度>
  • 我部分同意@billynoah。我使用 touchstart 作为 video.play() 的事件,它适用于所有浏览器,但似乎必须触发该事件两次才能在 FF mobile 81.1 中播放视频。所以如果用户触摸屏幕两次,视频就会播放,否则我会黑屏。我正在努力寻找更有效的方法
猜你喜欢
  • 2016-12-07
  • 2012-04-13
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-16
  • 2016-04-03
相关资源
最近更新 更多