Browser denying javascript play()

杀马特。学长 韩版系。学妹 提交于 2020-12-29 08:52:07

问题


I have a page with an input field for scanning products. When a barcode is scanned or a SKU is typed into the field, an ajax request is made and the application plays either a success or an error sound depending on the response using HTMLMediaElement.play().

sounds.error.play();

This was working fine a while ago but now I get this error:

⚠ Autoplay is only allowed when approved by the user, the site is activated by the user, or media is muted.

Followed by:

NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

Since this page only exists for the purpose of scanning SKUs, when the page loads, that input field is programmatically focused so as to make things easier on the end user. I tried removing this focus so that the user must click into the input field, but that doesn't appear to satisfy whatever the requirements are to allow playing of audio

After a bit more experimenting I found that with some additional amount of user interaction, the sound will play. For instance if I create a checkbox to "enable" the sound and the user clicks it, that appears to be enough. Or if the user clicks outside of the input element and then back into to it again that also works.

What exactly are the requirements that will satisfy most modern browsers so that they will allow playing of audio?

I realize the answer may be different for different browsers and configurations, but I was unable to find anything authoritative for current versions of either Firefox or Chrome. I'm looking for a workaround so that the application does not need to be complicated with extra clicks or other kinds of interactions, and since I am now aware of this new policy, I'd like the revisions to be as unobtrusive as possible.

UPDATE:

Here is a basic example I worked up to demonstrate the issue. I tried three different browsers just now and they all behaved a bit differently. Firefox in particular behaves as described above — does not play the sound until I focus on the input field, blur, then click to focus again:

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


回答1:


[edit] Firefox 70 fixes this issue. The rest of this answer provides an explanation and the proposed workaround.

As you wondered about what specifically "The user has interacted with the site" criteria means:

  • Note that there's currently no requirement for the autoplay to be triggered in response to a user gesture (though Mozilla considers changing this). The user must interact with the page to "activate" it, after which autoplay is allowed.
  • According to a comment in Firefox source code,

    ["activation" is triggered by] events which are likely to be user interaction with the document, rather than the byproduct of interaction with the browser (i.e. a keypress to scroll the view port, keyboard shortcuts, etc).

  • Specifically, in the current development version of Firefox, the following events do NOT make the page "user-gesture-activated" (code):

    • Events targeted at a text input or an editable document (e.g. contenteditable), e.g. typing/clicking on a text input; - this was the exception that affected your use-case; now removed in Firefox 70.
    • Key presses that don't correspond to printable characters, enter or space; or any keys pressed while holding modifiers, such as CTRL)
    • Touch events that are not taps (e.g. swiping, panning, scrolling)

An idea - start with a fake/blurred textbox, and show/focus the real textbox after the first character is typed (adding the first character to the text input via JS) - the following code appears to work in 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();
    }
})

This won't help if the user starts by clicking the text input, but a fallback non-audible feedback could be implemented for this case.




回答2:


There is some permission blocking in all modern browser (especially chrome) when comes down to autoplaying multimedia.

Here is the Autoplay availability's section from MDN which shows when the media will be allowed to execute automatically:

  • The audio is muted or its volume is set to 0;
  • The user has interacted with the site (by clicking, tapping, pressing keys, etc.)
  • If the site has been whitelisted; this may happen either automatically if the browser determines that the user engages with media frequently, or manually through preferences or other user interface features
  • If the autoplay feature policy is used to grant autoplay support to an <iframe> and its document.

This here is a similar solution for what you want with arrayBuffer using AJAX

here is a DEMO




回答3:


I struggled with that same issue as well and out of the blue I fixed that very easily:

Just change your event listener at your play button

onClick={togglePlay} to onClickCapture={togglePlay}

Example in React using hooks:

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>
    )
}


来源:https://stackoverflow.com/questions/57504122/browser-denying-javascript-play

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!