Safari 11 对 HTML5 音频的新自动播放限制

Posted

技术标签:

【中文标题】Safari 11 对 HTML5 音频的新自动播放限制【英文标题】:Safari 11's new autoplay restrictions on HTML5 Audio 【发布时间】:2017-06-19 11:19:21 【问题描述】:

我试图弄清楚 Safari 11(和 ios 的)自动播放限制是如何实现的,但我不明白为什么以下内容没有开始播放音频文件:

/*
    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'/>

而 Safari 可以满足以下条件:

/*
    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'/>

有人知道 Safari 如何确定某项内容是否为自动播放吗?我不是在寻找解决方法(例如,启动和暂停有帮助),但我正在尝试弄清楚它是如何工作的。

(有关 Safari 新的自动播放策略的更多背景信息可以在这里找到:https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/)

【问题讨论】:

我注意到我的网站使用了微妙的音效,不再播放它们。它们不是自动播放的,它们在完成任务后播放,由 javascript 激活。 这是我很久没有听到的声音了。 我相信这可能是因为您试图在移动设备上启动自动播放。 (假设您在 iOS 标题中发布)W3C 规定自动播放不应该在移动设备上运行,因为用户可能容易受到移动数据费用的影响 【参考方案1】:

你需要改变你的算法

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

user clicks -> changes source -> play

基本上您需要在audio 中更改src 并在用户单击播放按钮后立即开始播放。

当存在中间提取时,iOS 会阻止自动播放。

【讨论】:

【参考方案2】:

自动播放

audio.autoplay = true;

请注意,对于移动设备,W3C 已指定用户必须触发播放以避免移动数据费用。

因此,对于移动设备,您需要向用户展示触发自动播放的按钮。

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'/>

【讨论】:

以上是关于Safari 11 对 HTML5 音频的新自动播放限制的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 音频播放器未在 ios Safari 中自动播放

移动 safari 似乎在导航后卸载 html5 音频/视频

使用 HTML5 音频和 jQuery 对调用对象 (this) 的引用

youtube 如何在 Safari 上自动播放带音频的视频?

在 HTML5 中使用音频标签时如何避免主播重新播放音乐?

Safari 音频 HTML5 问题