天天看点

HTML 5 Audio/Video DOM canplaythrough 事件在移动端遇到的坑

canplaythrough 事件定义和用法

当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件。

当音频/视频处于加载过程中时,会依次发生以下事件:

  • loadstart
  • durationchange
  • loadedmetadata
  • loadeddata
  • progress
  • canplay
  • canplaythrough

浏览器支持

所有主流浏览器都支持 canplaythrough 事件。

注释:Internet Explorer 8 或更早的浏览器不支持该事件。

以上是w3cschool的解释,但是在我实验检测中,发现chrome,firefox对此事件是支持的,而移动端对此事件支持需要辅助方法。

我们在做移动端h5的时候,可能都会需要预加载资源,包含图片,音视频文件

var audio = new Audio();
audio.addEventListener("canplaythrough",function(){
    console.log("加载完成!");
},false);
audio.addEventListener("error",function(){
    console.log("加载失败!");
},false);
audio.src = src;      

看这段代码好像每错,在pc端检测也没有错,但是当我们放到h5上面就会出错,因为手机上面音乐是流媒体加载的,就是说在加载的过程中是可以播放的一边加载一边播放,canplaythrough 事件在移动端,只有允许audio/video文件加载播放完之后才会执行。

var audio = new Audio();
//canplaythrough这个事件在手机上流媒体要一边播放才能监听得到,pc端chrome可以完美支持
audio.addEventListener("canplaythrough",function(){
    //我们发现播放完之后这里执行了
    console.log("加载完成!");
},false);
audio.addEventListener("error",function(){
    console.log("加载失败!");
},false);
audio.src = src;
audio.play();      

但是这里会导致加载的时候就播放声音,那于是这样干

var audio = new Audio();
//canplaythrough这个事件在手机上流媒体要一边播放才能监听得到,pc端chrome可以完美支持
audio.addEventListener("canplaythrough",function(){
    audio.pause();
    audio.volume = 1;
    //我们发现播放完之后这里执行了
    console.log("加载完成!");
},false);
audio.addEventListener("error",function(){
    console.log("加载失败!");
},false);
audio.src = src;
audio.play();
audio.volume = 0;      

但是发现,效果不好,会出现停顿等现象。

于是最后想了一种方法,通过xmlHTTP来获取音频文件:

function createXHR(){
  try { return new XMLHttpRequest(); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
  try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
  return null;
}  

var xhr=createXHR();
xhr.onreadystatechange=function(){
    if(xhr.readyState == 4){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            callNext();
        }else{
            callNext();
        }
    }
};
scr = "song.mp3";
//true(异步)或 false(同步)
xhr.open("post",src,false);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
xhr.send()      

但是发现这样做还是不完美,发现音乐还是有延迟的现象;

欢迎大神拍砖,给出解决办法