iOS HTML5交互时,音频无法播放

最近两天在做和HTML5交互的工作,我们的HTML5是一个小的游戏页面,但是音频却没有播放。

尽管 HTML5 音频表现出色,但作为一个仍在开发的规范,它仍有很多局限。移动版 Safari 甚至引入了更多的限制。在本文中,您将了解 HTML5 在移动版 Safari 方面的局限性。一些工作示例提供了相应的解决方案和全面的变通方法。通过本文您将了解在移动版 Safari 中使用 audio sprite 的好处,并尝试使用几个独到的解决方案来绕过 iOS 中的 HTML5 局限。

HTML5 音频的局限性

HTML5 音频虽然很健壮,但有其局限性,这主要取决于它的实现。对于音乐播放器(点唱机播放器)或简单的声音效果,它很有效,但是对于声音密集的应用程序如游戏,它的表现不是很理想。

在移动版 Safari 中加载的页面上,不能自动播放音频文件。音频文件只能从用户触发的触摸(单击)事件加载。如果在 HTML 标记中使用了 autoplay 属性,那么移动版 Safari 将会忽略这个属性,并且不会在加载页面时播放此文件,如下所示:

<audio id=”audio” src=”audio_file.mp3″ autoplay></audio>

加载音频

除非由用户接触事件,比如通过 onmousedownonmouseuponclickontouchstart 触发事件,否则不能加载音频流。图 1 显示了这样的一个示例。

图 1. 在移动版 Safari 中加载音频的工作流

屏幕快照 2016-07-15 下午3.55.02

如果在加载页面时运行清单 4 中的代码,那么在移动版 Safari 中不会加载视频流,甚至不会下载该视频流。

清单 4. 在页面加载时播放音频流在默认情况下会失败

var audio = document.getElementById(‘audio’);

audio.play();

即便是 HTML markup 中使用了 preload 属性,移动版 Safari 仍会忽视此属性,并且不会加载此文件,除非由用户触摸事件,如清单 5 所示。

清单 5. 移动版 Safari 中不支持 preload 属性

<audio id=”audio” src=”audio_file.mp3″

preload=”auto”></audio>

查看并收听 本例的效果。

在桌面 Safari 上,在加载页面时,清单 5 中的代码会下载此音频文件。但是,在移动版 Safari 上,此属性会被忽视,并且不会下载此音频文件。

在初始化一个新的音频流时会有几秒的延时,这是因为 iOS 需要实例化一个新的音频对象。清单 6 显示了如何遭遇这种延时。

清单 6. 在切换音频对象时的 HTML5 音频延时

 var audio1 = document.getElementById(‘audio1’);

var audio2 = document.getElementById(‘audio2’);

audio1.play();

// at a later time

audio2.play();

// there will be a few-seconds delay as iOS is instantiating a new audio object.

// at an even later time

audio1.play(); // there will also be a few-seconds delay, as the audio object

// for audio1 in iOS was destroyed when we played audio2.

查看并收听 本例的效果。

重要的是确保您的逻辑不会假设音频流是在加载页面时载入的。调用 play() 在默认情况下会失败,如果在将要加载但尚未载入其元数据的音频流上尝试设置 currentTime,则会抛出一个致命错误,如清单 7 所示。

清单 7. 在一个尚未载入其元数据的音频流上设置 currentTime

// run on page load

var audio = document.getElementById(‘audio’);

audio.play(); // This will silently fail

audio.currentTime = 2; // This will throw a fatal error because the metadata

// for the audio does not exist

查看并收听 本例的效果。

音频文件不能缓存在 iOS 上的移动版 manifest 中。只有在对某个离线应用程序使用清单 (manifest) 时,这才适用。如果一个音频文件包含在此清单中,iOS 将会忽略它,并且不会缓存此文件。每当此 Web 应用程序需要访问此音频文件时,都需要从该网络访问此文件。

用 JavaScript 以编程方式进行相关设置时,移动版 Safari 并不会尊重此音量和 playbackRate 属性。更改属性也不会实际调整这些值。音量总是在用户控制下,并且 playbackRate 在移动版 Safari 中仍然不受支持。音量总是保持设置为 1,playbackRate 则会设置为希望设置的新值,但是音频流回放的实际速度不会发生改变。这会为 onratechange 事件带来某些复杂性,我们将在 不受支持的事件 部分对此进行讨论。

在 iOS 5 之前,循环属性是不受支持的。为了解决缺乏支持的问题,可以向 onended 事件添加了一个事件侦听程序,并在该函数中调用 play()。清单 8 显示了一个例子。

清单 8. iOS < 5 的音频循环变通方案

var audio = document.getElementById(‘audio’);

audio.play();

var onEnded = function() {

    this.play();

};

audio.addEventListener(‘ended’, onEnded, false);

查看并收听 本例的效果。

自动播放

对于自动播放的局限性,没有变通方案。正如前面所提及的,音频流只能从用户触摸事件加载。当针对移动版 Safari 进行开发时,重要的一点是要在必要时调整您的工作流,以适应这个局限性。

加载音频

音频流只在用户事件触发时才能加载。如清单 11 所示,onmousedownonmouseuponclickontouchstart 都是一些可用的事件,当在一个回调中调用它们时,可成功加载一个音频流。请注意,这种情况只适用于加载一个音频文件时,在一个已经加载的文件上调用 play() 会按预期的那样工作。

清单 11. 使用一个事件触发事件来加载一个音频流

// run on page load

var button = document.getElementById(‘button’);

var audio = document.getElementById(‘audio’);

var onClick = function() {

    audio.play(); // audio will load and then play

};

button.addEventListener(‘click’, onClick, false);

查看并收听 本例的效果。

不受支持的事件

事件

描述

桌面

移动版 Safari

abort

在媒体完全下载之前,浏览器停止获取媒体。

X

X

canplay

浏览器可恢复媒体数据的回放,但会做出评估:如果回放开启,在不会停下来做进一步的内容缓冲的情况下,媒体资源在结束操作前不会以目前的回放速度呈现。

X

X

canplaythrough

浏览器会做出评估:如果回放现在开始,那么在不停下来做进一步缓冲的情况下,媒体资源会以目前的回放速度呈现,一直到结束。

X

X

durationchange

duration 属性发生变化。

X

X

emptied

媒体元素网络状态更改成 NETWORK_EMPTY 状态。

X

X

ended

回放在媒体资源的终点停止,且 ended 属性被设置为 true。

X

X

error

在获取媒体数据前会发生错误。使用此 error 属性来获得当前的错误。

X

X

loadeddata

浏览器可以初次在目前的回放位置呈现媒体数据。

X

X

loadedmetadata

浏览器知道媒体资源的持续时间和大小。

X

X

loadstart

浏览器开始加载媒体数据。

X

X

pause

pause 方法返回后,回放暂停。

X

X

play

play 方法返回后,回放开始。

X

X

playing

回放开始。

X

X

progress

浏览器在获取媒体数据。

X

X

ratechange

defaultPlaybackRateplaybackRate 属性发生变化。

X

X (shouldn’t)

seeking

seeking 属性被设置为 true,且有时间发送此事件。

X

X*

seeked

seeking 属性被设置为 false

X

X*

stalled

浏览器获取媒体数据,但媒体数据不再到达。

X

X

suspend

浏览器暂停加载媒体数据,并且没有下载完全部的媒体资源。

X

X

timeupdate

currentTime 属性作为正常回放的一部分或因为某些其他条件发生变化。

X

X

volumechange

volume 属性或 muted 属性发生变化。

X

waiting

浏览器停止回放,因为它在等待下一帧。

X

X

分享到: 更多
Separator image Posted in IOS.