很久没有写过东西了,最近在帮朋友搞一个音乐方面的站点,因为涉及到H5播放音乐,所以考虑增加音频视觉效果更棒些,可是在使用canvas+AudioContext创建音乐播放可视化效果的时候,发现只要audio音频暂停后再次点击播放,浏览器就会报下面的错误:
Uncaught DOMException: Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode.
at analyzerInitialize (https://.../app.js?ver=1.6:40:25)
at HTMLDivElement.<anonymous> (https://.../app.js?ver=1.6:79:3)
at HTMLDivElement.dispatch (https://.../jquery.min.js?ver=1.6.87.30:3:12444)
at r.handle (https://.../jquery.min.js?ver=1.6.87.30:3:9173)
at C (https://...min.js?ver=1.6.87.30:6:6769)
at HTMLDocument.T (https://...min.js?ver=1.6.87.30:6:8938)
虽然不影响手机浏览器执行(用户几乎看不到),但是作为一只程序猿怎么会允许自己写的东西飘红呢?
于是开始各种排查,通过报错信息不难发现是因为HTMLMediaElement被占用而导致的,也就是说audio相关的元素已经被使用,当暂停以后再次点击播放的时候,加载createMediaElementSource(audio)就会造成错误,因为不是科班出身,无法用专业的语言来描述,勉强举个例子,用vue等前端框架经常遇到的插槽冲突的道理是一样的。知道了问题是怎么发生的,那么解决起来就相对简单了。html代码中编写的<audio>标签是固定的,那么如果使用javascript去创建标签,对于JS来讲每次创建的就都不一样了,于是删除html里面的audio标签,在原来的位置创建了一个id=audio_container的div,然后在JS里面加上:
......
//新增下面一行,用于通过JS创建audio元素
document.getElementById('audio_container').innerHTML = '<audio id=\"audio\"></audio>';
var audio = $('#audio');
audio.src = playUrl;
......
var audioSrc = actx.createMediaElementSource(audio);
......
保存后清空缓存重新加载,OK,红彤彤的一片不见了!哈哈,文章写的乱七八糟,希望能给遇到同样问题的朋友们一点提示,也给自己做个备忘。
洗洗赶紧睡了~