1. 程式人生 > >html5 audio實現歌詞同步

html5 audio實現歌詞同步

audio標籤用於播放音訊檔案,很不幸,歌詞檔案並沒有相應介面
addTextTrack() 向音訊新增新的文字軌道。//各大瀏覽器都沒有支援
有兩種方法可以實現歌詞同步:
1. 使用setInterval();
2. 監聽timeupdate
兩種方法,個人覺得都不是很完美,暫時找不到更好的方法

function media(dom,src){
    this.dom = dom;
    this.src = src;
    this.audio = this.dom.getElementsByTagName('audio')[0];
    this.control = $(this.dom).find(".control"
)[0]; this.lyrbox = $(this.dom).find(".lyrics")[0]; this.timer = this.dom.getElementsByTagName('span')[0]; this.timepoint = $(this.dom).find(".time-point")[0]; this.timebardiv = $(this.dom).find('.time-bar div')[0]; this.formatlyr = []; this.intval = null; this.init(); formattime = function
(t){
var min = parseInt(t/60); var ss = parseInt(t)%60 ; ss = ss>9?ss:"0"+ss; return min+":"+ss; } } media.prototype.init = function() { var self = this; self.dom.style["background"] = "url("+self.src.img+") no-repeat"; self.dom.style["background-size"] = "100% 100%"
; self.audio.src = self.src.mp3; self.audio.autoplay = true; self.lyr(); self.audio.addEventListener("canplay",function(){ self.timer.innerHTML = formattime(0)+ "/"+ formattime(self.audio.duration) ; self.control.style.display="block"; // self.control.style["transition"]="all 4s;" // self.audio.autoplay = true; self.audio.play(); if(self.intval) self.intval = null; self.intval = setInterval(function(){ var len = self.formatlyr.length; var _c = self.audio.currentTime; var p =$(self.lyrbox).find('p') for(var i=0;i<p.length;i++){ if(p[i].style['color'] != ''){ p[i].style['color'] = ''; break; } } for(var i=0;i<len;i++){ var _t = i?self.formatlyr[i-1][0]:0; var _t1 =i<len-1? self.formatlyr[i+1][0] :9999; if(_c >= _t && _c < _t1){ self.lyrbox.getElementsByTagName('p')[i].style['color'] = "#1D94E1"; $(self.lyrbox).css("transform","translateY(-"+(i?i-1:0)*32+"px)").css("transition-duration","0.5s"); break; } } var a=_c/self.audio.duration * (self.timebardiv.clientWidth - self.timepoint.clientWidth) ; $(self.timepoint).css("transform","translateX("+parseInt(a) +"px)"); self.timer.innerHTML = formattime(self.audio.currentTime)+ "/"+ formattime(self.audio.duration) ; },1000) ; }); self.ctrltime(); self.togglepause(); self.audio.canplay = function(){ alert('canplay'); } }; media.prototype.togglepause = function() { var self = this; $(".ctrl-pause ").on('click',function(){ $this = $(this).find('a'); if($this.hasClass("play")){ $this.addClass("pause"); $this.removeClass("play"); self.audio.pause(); }else if($this.hasClass("pause")){ $this.removeClass("pause"); $this.addClass("play"); self.audio.play(); }else{ } }); }; media.prototype.lyr = function() { var self = this; function parselyr(d){ var lines = d.split("\n"),pattern=/\[\d{2}:\d{2}.\d{2}\]/g,_l=[]; var fg = document.createDocumentFragment(); lines.forEach(function(i){ if(i.match(pattern)){ _l.push(i); } }); _l.forEach(function(i,index){ var s1 = i.split(']'),s2 = s1[0].slice(1),s3 = s2.split(':'); var second = parseInt(s3[0])*60 + parseFloat(s3[1]); var p = document.createElement('p'); p.innerHTML = s1[1]; fg.appendChild(p); self.formatlyr.push([second,s1[1]]); }); self.lyrbox.appendChild(fg); } $.get(this.src.lyrics,function(data){ parselyr(data); }); }; media.prototype.ctrltime = function() { // body... var self =this; self.timebardiv.addEventListener('click',function(e){ var dx = e.pageX - this.offsetLeft; var ct= parseInt(self.audio.duration*dx/this.clientWidth); self.audio.currentTime = ct; },false); }; $(document).ready(function(){ var m = new media(document.getElementById('playerbox'),sources[0]); });

只在firefox chorme&& android測試
注意理解canplay事件,這個事件可能會多次觸發。例如當你設定currentTime的時候,
也會觸發canplay事件,這個不好解釋 :(
第二種方法也差不多。
最後效果