HTML5 Audio的兼容性问题和优化

引入

(19.0205)本人在双十一期间,作的一个移动端互动项目中,遇到一个在 App 、微信、h5页面环境切换选择音频播放的功能,在测试的时候出了很多兼容性问题,这里有不少值得探索的知识,今天咱们就来看一下这个 HTML5-Audio。html

Audio 标签用于定义声音,好比音乐或其余音频流,HTML5 的 Audio 标签在很大程度上取代了 Flash 来播放音乐。html5

1、默认样式

Audio 标签在浏览器中的默认样式以下图所示,须要注意的一个地方:须要配置 controls 属性(是否显示默认控制条,是 Audio 标签的控制属性),不然不展现样式效果。git

2、Audio 支持的音频文件格式

一、OGG:github

OGG 是一种新的音频压缩格式,相似于 MP3 等的音乐格式。OGG 是彻底免费、开放和没有专利限制的。OGG 文件格式能够不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。web

二、MP3:chrome

MP3 是一种音频压缩技术,其全称是 Moving_Picture_Experts_Group_Audio_Layer_III(动态影像专家压缩标准音频层面3),简称为 MP3 。它被设计用来大幅度地下降音频数据量。将音乐以 1:10 甚至 1:12 压缩成容量较小的文件,而对于大多数用户来讲重放的音质与最初的不压缩音频相比没有明显的降低。浏览器

三、WAV:缓存

WAV 是微软公司开发的一种声音文件格式,它用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所普遍支持,标准格式化的 WAV 文件和 CD 格式同样,所以在声音文件质量和 CD 相差无几。微信

3、兼容性问题

咱们来从下面几个角度看兼容性问题:markdown

一、音频格式的兼容性

音频格式 Chrome Firefox IE9 Opera Safari
OGG 支持 支持 支持 支持 不支持
MP3 支持 不支持 支持 不支持 支持
WAV 不支持 支持 不支持 支持 不支持

说明:

Audio 标签默认支持的主流的音频文件格式有 MP三、WAV、OGG ,不一样的浏览器对三种格式支持程度不同。其中 MP3 格式支持度最好。

WAV 格式音质最好,可是文件体积较大。MP3 压缩率较高,普及率高,音质相比 WAV 要差。OGG 与 MP3 在相同位速率(Bit Rate)编码的状况下,OGG 体积更小,而且 OGG 是免费的不用交专利费(这点国人很中意)。

二、不一样浏览器对于 HTML5 Audio 标签的兼容性

说明:

在版本较新的浏览器中都是能够支持 Audio 标签的,在移动端上兼容性会更好一些。

4、使用方法

咱们常常会使用到的属性、方法、事件:

一、经常使用属性:

属性 属性值 注释
src url 播放的音乐的 url 地址(火狐只支持 OGG 的音乐,而 IE9 只支持 MP3 格式的音乐。chrome 貌似全支持)
preload preload 预加载(在页面被加载时进行加载或者说缓冲音频),若是使用了 autoplay 的话那么该属性失效。
loop loop 循环播放
controls controls 是否显示默认控制条(控制按钮)
autoplay autoplay 自动播放

二、经常使用方法:

函数 做用
load() 加载音频、视频软件
play() 加载并播放音频、视频文件或从新播放暂停的的音频、视频
pause() 暂停当前播放的音频

三、经常使用事件:

事件名称 事件做用
play play 和 autoplay 播放时
pause pause 方法触发时
ended 当前播放结束
timeupdate 当前播放时间发生改变的时候(播放中经常使用的时间处理)
canplaythrough 歌曲已经载入彻底完成
canplay 缓冲至目前可播放状态。

咱们能够经过 JS 代码来控制播放:

let audio = document.getElementById('audio');
audio.load();//加载
audio.play();//播放
audio.pause();//暂停
audio.loop = true;//循环播放
    
复制代码

5、问题与解决方案:

好的,咱们再来看具体看一下 Audio 标签的兼容性问题:

一、如何解决预加载问题

现状:preload 在 iOS 系统上的 safari 和微信是不支持的。

解决方法:**须要用户主动触发事件(Event)**才能进行播放。

示例代码:

$("#btn").click(function() {
    $("#audio").load();
})
复制代码

二、如何解决多个音频文件切换问题

现状:当时项目中有切换不一样音乐播放,若是采用更改 Audio 标签的 src 的方式,iOS 下会出现不能播放音乐或者播放延迟过高问题。

解决方法:这种 bug 出现的缘由是音频文件不能缓存在 iOS 系统上,每当页面访问其余音频文件时,都从网络访问音频文件,解决方法:能够在页面中声明多个 Audio 标签,把须要引入的音频文件预先引入,播放哪一个再调用相应文件,这个方案的缺点是在 iOS 系统下每个 Audio 占一个线程,若是有多个的 Audio ,则很占资源;或者把多个音频文件合并成为一个文件,播放其余音频的时候只须要调用合并以后的音频文件的相应时段,虽然比较繁琐,可是兼容性很好,能够参考下该音频合并工具(jsfiddle.net/aarongloege…

示例代码:

<audio src="" id="audio1"></audio>
<audio src="" id="audio2"></audio>
var audio1 = document.getElementById('audio1');
var audio2 = document.getElementById('audio2');
audio1.play();
audio2.play();
复制代码

三、如何解决自动播放问题

现状:iOS 端 safari 浏览器或者部分安卓手机的浏览器不支持 autoplay 属性。

解决方法:仍是引导用户手动触发播放操做。 好比绑定 touchstart 事件进行 audio.play() 操做,所以在和产品、测试同窗沟通确认的时候就须要确认好这个点。若是在微信环境下能够调用微信提供的插件( jweixin-1.0.0.js )。

示例代码:

wx.ready(function() {
    audio.play();
});
复制代码

四、如何解决播放数量问题

现状:一个 Audio 标签只能播放一个音频

解决方法:若是要同时播放多个音频,只得使用多个 Audio 标签,可是这个状况下要注意,各浏览器是是支持在同一页面播放多个音频的,而项目场景基本只容许播放一个音频,这个得注意控制播放当前音乐时要中止其余音乐项的播放

示例代码:

<audio src="a.mp3" src="a.mp3"></audio>
<audio src="b.mp3" src="b.mp3"></audio>
<audio src="c.mp3" src="c.mp3"></audio>
复制代码

五、如何解决移动端下音频混合播放问题

现状:在 iOS safari 下关闭浏览器窗口(切换至后台)或者切换标签时, Audio 仍然继续循环播放音频文件,若是关闭浏览器标签才会中止播放。

解决方法:使用循环存储时间来检查用户是否在网页上, timeupdate 事件是在音频 Audio 的播放位置发生改变时触发。

示例代码:

var lastSeen;
var loop = function (){
    lastSeen = Date.now();
    setTimeout(loop, 50);
};
loop();

var music = document.getElementById('music');
music.addEventListener('timeupdate', function (){
    if(Date.now() - lastSeen > 100){
        this.pause();
    }
}, false);
复制代码

六、如何解决续播问题

现状:在 JDApp 端页面音频播放时,切换至后台或者其余应用,音乐暂停播放以后,再切换至音乐播放的原页面,音乐没有继续播放。

解决方法:判断是不是在 JDApp 下,若是在 JDApp 使用 JDAppUnite 调用原生方法 callRouterModuleWithParams 控制音频继续播放。

示例代码:

function toOriginalChk(wvt, soundRouter) {
    // 判断环境
    if (wvt == 'notJdApp') {
        return;
    } else if (wvt == 'wk') {
        // 通知原生播放状态
        window.webkit.messageHandlers.JDAppUnite.postMessage({
            'method': 'callRouterModuleWithParams',
            'params': JSON.stringify(soundRouter)
        });
    } else if (wvt == 'ui') {
        window.JDAppUnite && window.JDAppUnite.callRouterModuleWithParams(JSON.stringify(soundRouter));
    }
}

复制代码

七、如何解决初始化延迟问题

现状:在 iOS safari 浏览器初始化一个新的音频流时会有几秒的延时。

解决方法:出现这 bug 的缘由是由于 iOS 须要实例化一个新的音频对象,再经过网络请求音频资源,音频资源加载完毕以后才能进行播放,解决方案:在页面 ready 以后把每一个文件都 load 一下,而后再调用 play 方法,这么作可使音频资源作预加载,提早请求网络,能够具体业务场景来优化使用。

(3) 示例代码:

$(function() {
    $("#audio1").load();
    $("#audio2").load();
})

复制代码

八、如何解决静音操做问题

现状:理想状况下用户能够在相关页面经过触发事件实现音频的静音操做

解决方法:能够经过设置 muted 属性来设置 Audio 静音,可是在 iOS 8及其如下 或者 IE9 及其如下版本不支持 muted 属性。

示例代码:

$("#audio").muted = true

复制代码

九、如何解决加载问题

现状:若是在页面未加载完成时调用 play 方法会失败,在这种状况下设置 currentTime 会抛出异常错误Failed to load resource: the server responded with a status of 404 ()

解决方法:遇到此类问题,能够先检查网络及音频大小以排除。

十、如何解决循环播放问题

现状:在 iOS 系统在 5 以前不支持循环属性。

解决方法:能够经过向 onEnded 事件添加了一个事件侦听程序,并在该函数中调用 play 方法解决。

示例代码:

var audio = document.getElementById('audio');
audio.play();

var onEnded = function() {
    this.play();
};

audio.addEventListener('ended', onEnded, false);
    
复制代码

小tip:HTML5 Audio 标签给咱们提供了一些额外的信息来指定播放哪一时间段,方法是在媒体文件后面跟随(“#”)格式

<audio src="audio.mp3#t=10,20"></audio>
// src="audio.mp3#t=10,20" (从10s播放到20s) 
// src="audio.mp3#t=10" (从10s播放到完) 
// src="audio.mp3#t=,10" (从开头播放到10s) 
 
复制代码

总结

HTML5 提供的 Audio 标签虽然有很多的兼容性问题, 可是在移动端使用音频播放, Audio 仍然是 HTML5 发展的大势所趋,值得咱们使用。本文介绍了 Audio 标签的使用方法以及音频文件的兼容版本和 Audio 在不一样环境下的兼容性问题并相应给出了解决方案。最后附上本身开发的插件( github.com/jdf2e/audio… ),扫二维码可访问:

image

以上提到的解决方案能够帮助你们解决大多数问题,若是须要更完善的规避这些 Audio 的坑能够参考使用这个 JS 插件,使用方法以下:

jdMusic.create([{
                src: 'https://jdch5.jd.com/yayoi/res/raw-assets/Sound/A.mp3',
                isloop: false,
                id: 'demo1',
                class: 'demo1',
                autoplay: false
            }, {
                src: 'https://jdch5.jd.com/yayoi/res/raw-assets/Sound/B.mp3',
                isloop: false,
                id: 'demo2',
                class: 'demo2',
                autoplay: true
            }]);
 jdMusic.play(0)
 jdMusic.pause()
复制代码

参考文献

[1] HTML 5 audio 标签

www.w3school.com.cn/html5/html5…

[2] HTML DOM Audio 对象

www.w3school.com.cn/jsref/dom_o…

[3] HTML5 Audio (音频)

www.runoob.com/html/html5-…

[4] audio sprite 工具

jsfiddle.net/aarongloege…

[5] audioCreate.js

github.com/jdf2e/audio…