阅读 18
HTML5中Audio使用踩坑汇总
-
Cannot read property 'catch' of undefined
原因:在调用play()时,现代浏览器返回的是一个promise,对于执行失败的,会触发一个Unhandled Promise Rejection,但是对于低版本的浏览器,调用play()并不会返回一个promise。
解决:应该在调用play()时做如下处理,增加对playPromise的判断
var playPromise = document.querySelector('video').play(); // In browsers that don’t yet support this functionality, // playPromise won’t be defined. if (playPromise !== undefined) { playPromise.then(function() { // Automatic playback started! }).catch(function(error) { // Automatic playback failed. // Show a UI element to let the user manually start playback. }); } 复制代码
-
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
原因:对于还没有设置src的audio,就直接设置currentTime是会触发一个INVALID_STATE_ERR异常的。即使是设置currentTime = 0也会触发这个异常
解决:在设置currentTime之前,必须先设置audio的src
参考资料: Offsets into the media resource
media .
currentTime
[ = value ]Returns the current playback position , in seconds.
Can be set, to seek to the given time.
Will throw an
INVALID_STATE_ERR
exception if there is no selectedmedia resource. Will throw anINDEX_SIZE_ERR
exception if the given time is not within the ranges to which the user agent can seek. -
NotAllowedError
原因:在调用play()时可能会触发一个NotAllowedError的reject,原因是因为浏览器在某些情况下播放失败,常见场景是,未通过点击的情况下调用play() ,或者点击事件的回调中是在下一个tick里调用的play,例如在setTimeout里调用的play,再或者新创建了很多个audio元素,但是并不是每个audio都是通过用户点击来调用的play()等等。
-
场景一:未通过点击等事件绑定,直接调用play(),触发NotAllowedError。解决方法,把调用play()的部分放在事件回调里,如下代码:
playButton.addEventListener("click", () => { audioElem.play() }, false); 复制代码
-
场景二:在点击事件回调中的下一个tick里调用play(),这种情况的示例代码如下,
// 错误代码示例 playButton.addEventListener("click", () => { setTimeout(() => { audioElem.play() }, 100) }, false); 复制代码
这种情况,某些版本【在iOS12.0.1亲测有坑】也会触发NotAllowedError异常,应该避免这种情况,可以考虑如下hack手段解决
// hack playButton.addEventListener("click", () => { audioElem.muted = true let p = audioElem.play() if (p !== undefined) { p.then(() => { audioElem.muted = false audioElem.pause() setTimeout(() => { audioElem.play() }, 100) }).catch((e) => { console.log(e) }) } }, false); 复制代码
-
场景三:创建了多个audio元素,但是并不是每个audio都是通过用户点击来调用的play()的,这时候某些版本【在iOS12.0.1亲测有坑】也会触发NotAllowedError异常。对于这种情况,最好的办法就是只创建一个audio元素,后面通过改变src来播放不同的音乐资源。只要audio通过了事件回调里调用过play,后续都可以直接调用play了,而无需再次绑定事件回调里去执行,并且这样也可以避免创建多个audio来减少内存使用。
playButton.addEventListener("click", () => { audioElem.src = "https://a.mp3" audioElem.play() }, false); // 后面其他地方,可以改变src来直接play audioElem.src = "https://b.mp3" audioElem.play() 复制代码
-
-
iOS 中页面隐藏和显示时,播放audio行为异常
原因:在某些iOS版本中【iOS12.0.1亲测有坑】,当我们监听页面隐藏和显示事件,在隐藏时调用pause() 暂停,显示时调用play()恢复播放。当 按下home键,页面进入系统后台时 ,pause()正常调用,audio被正常暂停,但是但再次进入页面,显示事件中调用play()就会出现异常了,
-
第一种异常,如果,我们只是单纯的调用
audioElem.play()
,不会抛出任何错误,但是audio实际却没有真正播放,无任何声音; -
第二种异常,如果我们每次在显示事件中执行如下代码中任意一种场景,都会在很多情况下会抛出一个 AbortError 异常,极少数情况才会正常播放。
//监听页面显示隐藏事件 addPageVisibilityListener(() => { // 隐藏时暂停 audioElem.pause() },() => { // 显示时恢复播放 // 重新直接赋值src audioElem.src = "https://b.mp3" audioElem.play() // 或者load // audioElem.load() // audioElem.play() }) 复制代码
解决:这两种异常行为应该都是iOS 12.0.1系统本身的bug。我们可以通过如下2中方式来避免这种两种异常的发生,
- 方式1, 显示load(),并监听canplaythrough,推荐使用这种方式
const playAudio = () => { audioElem1.removeEventListener('canplaythrough', playAudio) let p = audioElem.play() if (p !== undefined) { p.catch((e) => { console.log(e) }) } } //监听页面显示隐藏事件 addPageVisibilityListener(() => { // 隐藏时暂停 audioElem.pause() },() => { // 显示时恢复播放 audioElem.load() audioElem.addEventListener('canplaythrough', playAudio) }) 复制代码
- 方式2,通过setTimeout以及retry来hack避免这种异常发生
let playAudio = (retry: boolean) => { let p = audioElem.play(); if (p !== undefined) { p.catch((e) => { if (retry) { setTimeout(() => { playAudio(false); }, 0); } }); } } //监听页面显示隐藏事件 addPageVisibilityListener(() => { // 隐藏时暂停 audioElem.pause() },() => { // 显示时恢复播放 setTimeout(() => { playAudio(true) }, 500) }) 复制代码
-
以上所述就是小编给大家介绍的《HTML5中Audio使用踩坑汇总》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- TokuDB 使用问题汇总
- 【iOS 开发】ReactiveObjC(RAC)的使用汇总
- 使用Spring Data Jpa遇到问题汇总
- Nacos使用中的常见问题汇总
- 近期使用新冠疫情(COVID-19)为诱饵的APT攻击活动汇总
- Redis 应用场景汇总
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web开发实例大全(基础卷)
软件开发技术联盟 / 清华大学出版社 / 2016-1 / 128.00
《Java Web开发实例大全(基础卷)》筛选、汇集了Java Web开发从基础知识到高级应用各个层面约600个实例及源代码,每个实例按实例说明、关键技术、设计过程、详尽注释、秘笈心法的顺序进行了分析解读。全书分为6篇23章,主要内容有开发环境搭建、Java语言基础、HTML/CSS技术、JSP基础与内置对象、JavaBean技术、Servlet技术、过滤器与监听器技术、JSTL标签库、JavaS......一起来看看 《Java Web开发实例大全(基础卷)》 这本书的介绍吧!