Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safari 11's new autoplay restrictions on HTML5 Audio

I'm trying to figure out how Safari 11's (and iOS') autoplay restrictions are implemented and I don't understand why the following doesn't start playing the audio file:

/*
    Call stack, this doesn't work 💩
*/

const btn = document.createElement('BUTTON')
const textLabel = document.createTextNode('Play')
const audio = new window.Audio()
audio.src = 'https://raw.githubusercontent.com/vnglst/autoplay-tutorial/master/mp3/winamp.mp3'
// audio.controls = true

btn.appendChild(textLabel)
document.getElementById('root').appendChild(btn)
document.getElementById('root').appendChild(audio)

btn.onclick = e => {
  window
    .fetch(`https://api.github.com/repos/vnglst/autoplay-tutorial/contents/mp3/modem-sound.mp3`)
    .then(resp => resp.json())
    .then(json => {
      audio.src = json.download_url
      audio.play()
    })
}
<div id='root'/>

Whereas Safari is fine with the following:

/*
    Call stack, using a fake Promise. This works 👍
*/

const btn = document.createElement('BUTTON')
const textLabel = document.createTextNode('Play')
const audio = new window.Audio()
audio.src = 'https://raw.githubusercontent.com/vnglst/autoplay-tutorial/master/mp3/modem-sound.mp3'
// audio.controls = true

btn.appendChild(textLabel)
document.getElementById('root').appendChild(btn)
document.getElementById('root').appendChild(audio)

const mockedPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const src = 'https://raw.githubusercontent.com/vnglst/autoplay-tutorial/master/mp3/winamp.mp3'
    return resolve(src)
  }, 500)
})

btn.onclick = (e) => {
  mockedPromise.then(src => {
    audio.src = src
    audio.play()
  })
}
<div id='root'/>

Does anybody know how Safari determines whether something is an autoplay or not? I'm not looking for a work around (starting and pausing helps for instance) but I'm trying to figure out how this works.

(some more background information on Safari's new autoplay policy can be found here: https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/)

like image 460
vnglst Avatar asked Jun 19 '17 11:06

vnglst


People also ask

How do I change autoplay settings in Safari?

In the Safari app on your Mac, choose Safari > Preferences, then click Websites. Click Auto-Play in the list on the left. Do any of the following: Choose settings for a website in the list: Select the website on the right, then choose the option you want for it.

Does Safari allow video autoplay?

In Safari, go to "Settings for This Website." Go to the right of Auto-Play, and click the pop-up menu to choose your preferred option: Allow All Auto-Play. Stop Media with Sound.

Can you autoplay audio in HTML?

The HTML <audio> autoplay attribute is used to specify that the audio should automatically start playing as soon as it is loaded. It is a Boolean attribute.


1 Answers

You need to change your algorithm from

user clicks -> loads audio information -> changes source -> play

to

user clicks -> changes source -> play

Basically you need to change src in audio and start playback right after user clicks play button.

iOS prevents autoplay when intermediary fetching is present.

like image 111
Artem Bernatskyi Avatar answered Nov 03 '22 00:11

Artem Bernatskyi