html5 audio總結

前言

 

  html5中對音頻,視頻播放原生支持.最近作了一個音樂播放器,得益於快過年了,才能抽出一點時間來總結一下.總的來講,html5對audio的支持很是強大, 難怪flash要死.瀏覽器上裝播放插件的時代已經接近尾聲了.目前大多數瀏覽器都支持了大部分經常使用的api,ie8及其之前除外(萬惡的ie啊).css

  HTML5 音頻雖然很健壯,但有其侷限性,這主要取決於它的實現。對於音樂播放器(點唱機播放器)或簡單的聲音效果,它頗有效,可是對於聲音密集的應用程序如遊戲,它的表現不是很理想。因此有了Web Audio API (Chrome) 和 Audio Data API (Firefox) 無需任何瀏覽器插件便可進行合成和動態處理音頻的能力來幫助人們解決特性缺失的問題.Web Audio與audio標籤不一樣,它給了開發者對音頻數據進行處理、分析的能力,例如混音、過濾等,相似於對音頻數據進行PS。通常的網站應用應該是用不倒這些API中的,可是一些遊戲引擎或者在線音樂編輯等類型的網站應該用獲得。請參考文章最後的參考資料.html

 

兼容狀況

 

可見除了ie6,7,8 和opera,其餘都支持了.其中安卓在2.1就已經支持了.audio的兼容性仍是不錯的,固然這只是audio標籤.JavaScript接口的支持狀況就各不相同了,可能會遇到坑.html5

 

API

原本想貼上audio的api,後來發現太多了,就放棄了.有不少都是不經常使用的.咱們這裏就討論幾個經常使用的api和屬性.ios

詳情請參考w3c http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp git

總結的過程當中也發現audio和video的api是如出一轍的.這也方便了廣大開發者的學習使用.github

 

重要方法

  • 這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的最大靈活性前提下,減小咱們的代碼量.web

js代碼chrome

;(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/APlayerapi

 

坑爹集錦

 

編程總不會這麼一路順風,莫名其妙的問題老是不會少的.下面就羅列一下我遇到的坑吧.

  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

window.HTMLAudioElement  能夠經過這個屬性來判斷是否支持audio

另一個解決方案就是使用第三方庫了,這裏推薦一個庫jplayer,聽說是支持ie7+和其餘的瀏覽器

jplayer中文文檔

 

總結

 

過年啦,祝你們新年快樂!  2016年但願我能成長得更多.

 

參考資料

 

相關文章
相關標籤/搜索