浏览器拒绝javascript play()

bil*_*oah 12 javascript audio firefox google-chrome

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

sounds.error.play();
Run Code Online (Sandbox Code Playgroud)

前一阵子工作正常,但现在我收到了这个错误:

only仅当获得用户批准,网站被用户激活或媒体被静音时,才允许自动播放。

其次是:

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

由于此页面仅出于扫描SKU的目的而存在,因此,在页面加载时,该输入字段将以编程方式集中显示,从而使最终用户的操作更加轻松。我尝试删除此焦点,以便用户必须单击输入字段,但这似乎无法满足允许播放音频的任何要求

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

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

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

更新:

这是我努力演示该问题的基本示例。刚才我尝试了三种不同的浏览器,它们的行为都有所不同。Firefox的行为如上所述特别重要-在我专注于输入字段,模糊然后单击再次聚焦之前,它不会播放声音:

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

小智 25

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

<video autoplay="" muted="" playsinline=""></video>
Run Code Online (Sandbox Code Playgroud)

  • 这为我做到了!非常感谢 (4认同)
  • 这应该被接受的答案,这适用于所有浏览器,在 chrome、safari 中进行了测试。 (3认同)
  • 我很高兴这个答案对某些人有用,但请注意,它确实解决了我的具体问题,具体是关于使用从 ajax 响应构建的 Audio() 构造函数播放音频文件。 (2认同)

小智 15

我也遇到了同样的问题,突然间我很容易解决了这个问题:

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

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

  • `onClickCapture={togglePlay}` 为我做到了。老实说,这种奇怪的行为看起来像是一个 Safari 错误,因为我没有自动播放,并且用户已经与该网站进行了交互。 (2认同)

Nic*_*lay 10

[编辑] Firefox 70修复了这个问题。此答案的其余部分提供了解释和建议的解决方法。

当你想知道什么特别的“用户与网站进行互动的”标准方式:

  • 请注意,当前不需要响应用户手势触发自动播放(尽管 Mozilla考虑更改 this)。用户必须与页面交互以“激活”它,然后允许自动播放。
  • 根据Firefox 源代码中评论

    [“激活”由] 事件触发,这些事件可能是用户与文档的交互,而不是与浏览器交互的副产品(即滚动查看端口的按键、键盘快捷键等)。

  • 具体来说,在当前的 Firefox 开发版本中,以下事件不会使页面“用户手势激活”(代码):

一个想法 - 从一个假的/模糊的文本框开始,在输入第一个字符后显示/聚焦真正的文本框(通过 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();
    }
})
Run Code Online (Sandbox Code Playgroud)

如果用户通过单击文本输入开始,这将无济于事,但可以在这种情况下实施后备非听觉反馈。

  • 感谢您在这里阐明了一些关键点。我仍然觉得这个标准有点模糊,导致了我所经历的不一致的行为。虽然这样的事情通常有利于网络浏览体验,但对于像我这样开发不适合公众的私人网络应用程序的人来说,它们是一个祸根。我们喜欢以前的行为,现在工作人员必须无缘无故地进行额外的点击。我希望有一个解决方法可以让我到达那里......还有一个问题 - 你能在最后解释一下你的想法吗?我不明白这会/能够/可能有什么帮助。 (2认同)
  • 我也不明白这些规则背后的动机。我[在错误中询问这是在哪里实现的](https://bugzilla.mozilla.org/show_bug.cgi?id=1452536#c37)。 (2认同)

Lui*_*bro 8

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

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

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

这是针对使用AJAX的arrayBuffer的解决方案

这是一个演示

  • “*用户已与网站进行交互*” - 这部分是我正在努力解决的问题。因为正如我所说,仅仅单击该字段似乎还不够。我至少必须点击退出,然后再次进入,因此 MDN 上的声明是不明确的,因为似乎存在一个“交互阈值”,而我正在寻找关于该阈值到底是什么的明确信息。 (4认同)