html5 audio总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了html5 audio总结相关的知识,希望对你有一定的参考价值。

前言

 

  html5中对音频,视频播放原生支持.最近做了一个音乐播放器,得益于快过年了,才能抽出一点时间来总结一下.总的来说,html5对audio的支持非常强大, 难怪flash要死.浏览器上装播放插件的时代已经接近尾声了.目前大多数浏览器都支持了大部分常用的api,ie8及其以前除外(万恶的ie啊).

  HTML5 音频虽然很健壮,但有其局限性,这主要取决于它的实现。对于音乐播放器(点唱机播放器)或简单的声音效果,它很有效,但是对于声音密集的应用程序如游戏,它的表现不是很理想。所以有了Web Audio API (Chrome) 和 Audio Data API (Firefox) 无需任何浏览器插件即可进行合成和动态处理音频的能力来帮助人们解决特性缺失的问题.Web Audio与audio标签不同,它给了开发者对音频数据进行处理、分析的能力,例如混音、过滤等,类似于对音频数据进行PS。一般的网站应用应该是用不倒这些API中的,但是一些游戏引擎或者在线音乐编辑等类型的网站应该用得到。请参考文章最后的参考资料.

 

兼容情况

 

技术分享

可见除了ie6,7,8 和opera,其他都支持了.其中安卓在2.1就已经支持了.audio的兼容性还是不错的,当然这只是audio标签.javascript接口的支持情况就各不相同了,可能会遇到坑.

 

API

本来想贴上audio的api,后来发现太多了,就放弃了.有很多都是不常用的.我们这里就讨论几个常用的api和属性.

详情请参考w3c http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp 

总结的过程中也发现audio和video的api是一模一样的.这也方便了广大开发者的学习使用.

 

重要方法

技术分享

  • 这3个方法是最基础的了,看方法名就知道是干嘛用的了.其中load方法,一般是在改变audio的一些属性后,需要重新加载的情况下使用.

 

重要属性

技术分享

  • autoplay 设置是否自动播放音频/视频,ios的Safari下不能自动播放,需要和用户交互后才能播放,这是个坑,后面会详细说.
  • buffered 会返回一个TimeRanges对象,包含一个起点和终点时间,如果用户拖动音频/视频,则有多个buffer区间,可以通过index访问指定buffer区间.

 

技术分享

技术分享

技术分享

  • currentTime 是非常重要的一个属性了,可以返回当前的播放位置(以秒计),同时也可以设置播放位置,跳跃播放音频.

 

技术分享

  • played 返回已经播放部分的TimeRanges对象,可以用于做一些计算

 

技术分享

  • seekable 表示用户当前可以跳跃观看的以缓冲部分区间
  • src 音频/视频资源地址

 

技术分享

  • volume 控制音量

 

重要事件

技术分享

  • 加载过程的事件流对我们做一些特殊处理是很有帮助的

 

技术分享

  • canplay 加载ok,可以播放时触发,一般逻辑都从这里开始
  • canplaythrough 当全部加载完毕时触发

 

技术分享

  • 正在下载时触发,配合buffered属性更新加载进度条的逻辑就可以放在这里

 

技术分享

  • 用户跳跃播放时触发

 

技术分享

  • 当前播放位置改变时触发,更新播放时间,同步歌词的逻辑都可以放在这里

 

封装audio

  从audio提供的api来说,已经非常强大和完善了.如果是在移动端,我们完全可以尽可能的使用原生api,没必要使用第三方库.我简单封装了一下audio,尽可能的保持原生api的最大灵活性前提下,减少我们的代码量.

js代码

;(function(){

    var _init = function(){
        var audio = this.audio = document.createElement(‘audio‘);
        for( var prop in this.audioProp ){
            audio[prop]  = this.audioProp[prop];
        }
        document.body.appendChild(audio);
    };

    var _bindEvt = function(){
        var audio  = this.audio,
            audioEvt = this.audioEvt;
        for( var func in audioEvt ){
            audio.addEventListener(func,audioEvt[func].bind(this),false);
        }
    };

    var _extend = function(o1,o2){
        for(var attr in o2)    {
            o1[attr] = o2[attr];
        }
        return o1;
    };

    /*
     *   构造函数
     */
    function Constructor(opton){
        opton =    _extend({
            audioProp : {

            },
            audioEvt : {
            
            },
            cssSelector : {
                
            }
        
        },opton);

        _extend(this,opton);
        _init.call(this);
        _bindEvt.call(this);
    }

    _extend(Constructor.prototype,{
        /*
         *   播放
         *     second 指定当前的播放时间 
         */
        play : function(second){
            second && (this.audio.currentTime = second);
            this.audio.play();        
        },

        /*
         *   暂停
         *   second 指定当前的播放时间
         */
        pause : function(second){
            second && (this.audio.currentTime = second);
            this.audio.pause();    
        },


        /*
         *   时间格式化
         *     00:00
         */
        timeFormat : function timeFormat(number) {
            var minute = parseInt(number / 60);
            var second = parseInt(number % 60);
            minute = minute >= 10 ? minute : "0" + minute;
            second = second >= 10 ? second : "0" + second;
            return minute + ":" + second;
        }
    
    });


    //兼容amd,cmd,原生js接口
    if(typeof module !== ‘undefined‘ && typeof exports === ‘object‘ && define.cmd){
        module.exports = Constructor;    
    }else if(typeof define === ‘function‘ && define.amd){
        define(function(){
            return Constructor;    
        });
    }else{
        window.APlayer = Constructor;    
    }

})();

html代码

        var music = new APlayer({
            audioProp : {
                title : ‘给我一个理由忘记‘,
                loop : true,
                src : "https://ss1.baidu.com/8aQDcnSm2Q5IlBGlnYG/stat/ogg/xinsui.mp3",
            },
            audioEvt : {
                canplay : function(){
                },
                timeupdate : function(){
                    $(‘.currentTime‘).html(this.timeFormat(this.audio.currentTime));  
                }
            }

        });

        $(".play").on("touchend",function(){
            music.play();    
        });
        $(".pause").on("touchend",function(){
            music.pause(5);    
        });

详情可以看我的github   https://github.com/Alan110/desire/tree/master/APlayer

 

坑爹集锦

 

编程总不会这么一帆风顺,莫名其妙的问题总是不会少的.下面就罗列一下我遇到的坑吧.

  1.  安卓uc浏览器下,对timeupdate事件支持不好,只会很少的触发几次.这是什么概念,就是说我们基本上不能同步当前的播放时间和进度条了,还有歌词.

    解决方案:暂时没有

  2.  在ios,Safari下,不能自动播放,autoplay,preload属性无效. 或者audio.src=‘xx‘ , 加载完后手动调用audio.play()也是不行的.

    原因: 在ios,Safari下要求与用户交互后才加载歌曲,播放歌曲,如touchstart , touchend , click等事件. 

    解决方案 : 在iphone4下touchstart无效, 目测是因为性能不够无法捕捉. 改用touchend就好了

  3.  ios,Safari同一时间只能播放但音频/视频

    解决方案 : 使用 audio sprite 是满足移动 Safari 中多音效需求的最佳解决方案。与 CSS image sprite 类似,audio sprite 可以将所有的音频综合到一个音频流.要注意的是更改 currentTime 并不是百分百正确的。

           将 currentTime 设为 6.5,而实际得到的却是 6.7 或 6.2。每个 A sprite 之间需要少量的空间,以避免寻找到另一个 sprite 的尾部。

技术分享
// audioSprite has already been loaded using a user touch event
var audioSprite = document.getElementById(‘audio‘);
var spriteData = {
    meow1: {
        start: 0,
        length: 1.1
    },
    meow2: {
        start: 1.3,
        length: 1.1
    },
    whine: {
        start: 2.7,
        length: 0.8
    },
    purr: {
        start: 5,
        length: 5
    }
};

// play meow2 sprite
audioSprite.currentTime = spriteData.meow2.start;
audioSprite.play();
View Code

    记得播放完毕手,要手动停止

技术分享
var handler = function() {
    if (this.currentTime >= spriteData.meow2.start + spriteData.meow2.length) {
        this.pause();
    }
};
audioSprite.addEventListener(‘timeupdate‘, handler, false);
View Code

 

音频在低版本浏览器中的兼容

 

现代浏览器基本上都支持audio了,老版本的浏览器,如ie8及其以前的.兼容方案多是用flash来播放音频/视频.在页面中嵌入embed标签,或者object标签,来调用flash插件.

网上找了2段代码,手中无ie浏览器并不确定是否可用,看到的朋友慎重使用

技术分享
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="1" height="1">

  <param name="movie" value="flash/music.swf" />

  <param name="quality" value="high" />

  <embed src="flash/music.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="1" height="1"></embed>

</object>
View Code
技术分享
if(navigator.userAgent.indexOf("Chrome") > -1){
     如果是Chrome:
     <audio src="" type="audio/mp3" autoplay=”autoplay” hidden="true"></audio>
    }else if(navigator.userAgent.indexOf("Firefox")!=-1){
     如果是Firefox:
     <embed src="" type="audio/mp3" hidden="true" loop="false" mastersound></embed>
    }else if(navigator.appName.indexOf("Microsoft Internet Explorer")!=-1 && document.all){
      如果是IE(6,7,8):
      <object classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95"><param name="AutoStart" value="1" /><param name="Src" value="" /></object>
    }else if(navigator.appName.indexOf("Opera")!=-1){
       如果是Oprea:
       <embed src="" type="audio/mpeg"   loop="false"></embed>
    }else{
       <embed src="" type="audio/mp3" hidden="true" loop="false" mastersound></embed>
    }
View Code

另外一个解决方案就是使用第三方库了,这里推荐一个库jplayer,据说是支持ie7+和其他的浏览器

jplayer中文文档

 

总结

 

过年啦,祝大家新年快乐!  2016年希望我能成长得更多.

 

参考资料

 

    

以上是关于html5 audio总结的主要内容,如果未能解决你的问题,请参考以下文章

html5 audio总结

<audio>标签为啥IE 不兼容

html5 audio标签相关知识点总结

html5的audio,audio.play()在手机浏览器中不能自动播放

前端面试题总结

html5都有哪些新特性,移除了那些元素?如何处理html5新标签的浏览器兼容问题?