Safari 11's new autoplay restrictions on HTML5 Audio
up vote
12
down vote
favorite
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/)
javascript ios safari html5-audio
add a comment |
up vote
12
down vote
favorite
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/)
javascript ios safari html5-audio
1
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
1
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
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/)
javascript ios safari 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/)
/*
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'/>/*
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'/>/*
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'/>/*
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'/>javascript ios safari html5-audio
javascript ios safari html5-audio
edited Jun 26 at 15:59
asked Jun 19 '17 at 11:19
vnglst
1408
1408
1
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
1
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16
add a comment |
1
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
1
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16
1
1
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
1
1
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16
add a comment |
2 Answers
2
active
oldest
votes
up vote
0
down vote
Autoplay
audio.autoplay = true;
Please note that with mobile devices W3C have specified the user must trigger the playback in order to avoid mobile data charges.
Therefore with mobile devices, you will need to present the user with the button to trigger the autoplay.
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.autoplay = true;
// 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'/>add a comment |
up vote
0
down vote
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.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
Autoplay
audio.autoplay = true;
Please note that with mobile devices W3C have specified the user must trigger the playback in order to avoid mobile data charges.
Therefore with mobile devices, you will need to present the user with the button to trigger the autoplay.
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.autoplay = true;
// 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'/>add a comment |
up vote
0
down vote
Autoplay
audio.autoplay = true;
Please note that with mobile devices W3C have specified the user must trigger the playback in order to avoid mobile data charges.
Therefore with mobile devices, you will need to present the user with the button to trigger the autoplay.
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.autoplay = true;
// 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'/>add a comment |
up vote
0
down vote
up vote
0
down vote
Autoplay
audio.autoplay = true;
Please note that with mobile devices W3C have specified the user must trigger the playback in order to avoid mobile data charges.
Therefore with mobile devices, you will need to present the user with the button to trigger the autoplay.
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.autoplay = true;
// 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'/>Autoplay
audio.autoplay = true;
Please note that with mobile devices W3C have specified the user must trigger the playback in order to avoid mobile data charges.
Therefore with mobile devices, you will need to present the user with the button to trigger the autoplay.
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.autoplay = true;
// 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'/>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.autoplay = true;
// 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'/>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.autoplay = true;
// 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'/>answered Jul 15 at 23:11
DataCure
359115
359115
add a comment |
add a comment |
up vote
0
down vote
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.
add a comment |
up vote
0
down vote
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.
add a comment |
up vote
0
down vote
up vote
0
down vote
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.
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.
edited Nov 16 at 14:43
answered Nov 11 at 14:59
Artem Bernatskyi
6381519
6381519
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44629198%2fsafari-11s-new-autoplay-restrictions-on-html5-audio%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I'm noticing my website, which uses subtle sound effects, no longer plays them. They are not auto-play, they play upon completion of a task, activated by javascript.
– l008com
Sep 22 '17 at 7:34
1
Now that's a sound I've not heard in a long time.
– fuzz
May 1 at 5:56
I believe this may be because your trying to initiate an auto play on a mobile device. (given you posted in the title iOS) W3C speficies that auto play should not work on mobile devices as a result of mobile data charges a user could be susceptible to
– DataCure
Jul 15 at 12:16