注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

phperwuhan的博客

记载一个phper的历程!phperwuhan.blog.163.com

 
 
 

日志

 
 

php+js,实现mp3和LRC歌词高亮同步显示  

2010-03-31 09:42:58|  分类: php |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

来源:http://hi.baidu.com/dcyhldcyhl/blog/item/fa1535cfed4de030b700c8cc.html/cmtid/7cb500a5fa8c3ffc9152eedf

加了算法,可以处理所有lrc文件,只要百度mp3能同步的lrc,都可以。

思路很简单,file过来以后,逐行处理,多个时间段的话,就取当前段+该行歌词(正则过滤掉其他时间段)。存入临时文件。循环。

最后得到一个乱排序的标准时间序列+歌词的形式的一个文本。使用排序算法排下序。传递给js就可以了。

另外加了offset判断,如果lrc本身设置了偏移量,就按照lrc的偏移量走,如果没有,则设置为500毫秒。这个没有办法,没有offset 只能凭感觉了,我觉得500最合适。感觉百度设低了,同样的歌,百度的延迟要比我大很多,比较恶心。不过这个东西也只是模拟,无法实现像百度mp3那样的暂停,拖动等等的歌词同步。

---------------------------完整代码------------------------------

<?
/* powered by:sunlion            */
/* hi.baidu.com/sungoogle*/
/* QQ:37470931                   */
?>
<style type="text/css">
body {font-size:12px}
</style>
<script language="javascript">
//初始化播放器
function playerinit()
{
player.settings.autoStart = false ;
}
</script>
<?
$file = "E:/1.mp3";
if (!file_exists($file)) {exit('文件不存在.');}
$player = new COM("WMPlayer.OCX");
$media          = $player->newMedia($file); //获取时长
$time=($media->duration)*1000; //换算成毫秒
/*这个算法把每行多个时间段的lrc处理成,每个时间段后跟一行歌词的格式,并存入文本*/
if (file_exists("test.lrc.over.txt")) {unlink("test.lrc.over.txt");}
$fp=fopen("test.lrc.over.txt",'a');
$lines=file("test.lrc.txt");
foreach ($lines as $line) { //遍历lrc文件
preg_match_all("/\[.*?\]/is",$line,$tmptime); //提取[],判断该行有几个时间
$tmp=count($tmptime,1)-1; //返回[]个数
if ($tmp>1) {
     for ($i=0;$i<$tmp;$i++) {
     $tmpgeci=preg_replace("/\[.*?\]/is","",$line);
     fwrite($fp,$tmptime[0][$i].$tmpgeci); //提取当前[]并&正则过滤[]后的歌词
     }
} else {
     fwrite($fp,$line); //如果只有一个[],则直接将该行写入临时文本
}
}
fclose($fp);
/*这部分处理获得的文本,并把时间和歌词各自提取出来进行排序*/
$lines=file("test.lrc.over.txt");
foreach ($lines as $line) {
preg_match("/(?<=\[).*?(?=\])/is",$line,$write); //正则提取时间
$new=str_replace(".",":",$write[0]); //把.用:替换
list($min,$sec,$hm)=explode(":",$new); //切分时间
if ($min=="offset") {$offset=$sec;} //检查lrc中是否设置了offset
if ($min!="ti" && $min!="ar" && $min!="al" && $min!="by" && $min!="offset") { //忽略lrc版权等信息
$final=$min*60*1000+$sec*1000+$hm; //把时间换算成毫秒
$tmpgeci=preg_replace("/\[.*?\]/is","",$line);
$times[]=$final;
$array[]=$tmpgeci;
}
}
//冒泡排序,得到干净的歌词数组和时间序列数组
for ($i=0;$i<count($times);$i++) {
        for ($j=count($times)-2;$j>=$i;$j--){
               if($times[$j+1]<$times[$j]){
                    $tmp=$times[$j+1];
        $tmp2=$array[$j+1];
                    $times[$j+1]=$times[$j];
        $array[$j+1]=$array[$j];
                    $times[$j]=$tmp;
        $array[$j]=$tmp2;
                }
        }
}
if (file_exists("test.lrc.over.txt")) unlink("test.lrc.over.txt");
$tmp=count($array);
$temp=count($times);
echo "<script>cishu='$temp'</script>;";
echo "<script>offset='$offset'</script>";
?>
<script> //把php数组转化为js数组
var times=new Array();
<? for ($i=0;$i<$temp;$i++) {?>
           times[<?=$i?>]=<?=$times[$i]?>;
<? }?>
</script><body onLoad="display(cishu,times);">
<SCRIPT LANGUAGE="JavaScript">
var ms = 0;
var state = 0;
function startstop() {
if (player.controls.isavailable('play')) {player.controls.play();} //播放
if (state == 0) {
state = 1;
then = new Date();
then.setTime(then.getTime() - ms);
} else {
state = 0;
now = new Date();
ms = now.getTime() - then.getTime();
document.stpw.time.value = ms;
           }
}
function display(cishu,times) {
setTimeout("display(cishu,times);", 50);          //递归调用
if (state == 1)          {now = new Date();
ms = now.getTime() - then.getTime();
document.stpw.time.value = ms; //显示毫秒进度,调试用
          for (var i=0;i<cishu;i++) {
        var js_offset;
     js_offset=offset==""?500:offset; //如果lrc中不含offset设置,就把偏移量设置为500毫秒
           if (ms>=times[i]-js_offset && ms<=(times[i])) { //偏移量
           var obj=document.getElementById("s"+i);
           if (i>=1) {
           var objs=document.getElementById("s"+(i-1));
           objs.style.color="#000000";
     objs.style.fontWeight="normal";
           }
           obj.style.color="#FF5A00";
     obj.style.fontWeight="bold"; //加粗文字,网上找了半天还,汗...
           }
          }
           }
}
</SCRIPT>
<object id="player" width="350" height="64" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,7,1112"
align="baseline" border="0" standby="Loading Microsoft Windows Media Player components..."
type="application/x-oleobject">
            <param name="URL" value="E:/1.mp3">
            <param name="autoStart" value="false">
            <param name="invokeURLs" value="false">
            <param name="playCount" value="100">
            <param name="defaultFrame" value="datawindow">
       
          <embed src="E:/1.mp3" align="baseline" border="0" width="350" height="68"
           type="application/x-mplayer2"
           pluginspage=""
           name="MediaPlayer1" showcontrols="1" showpositioncontrols="0"
           showaudiocontrols="1" showtracker="1" showdisplay="0"
           showstatusbar="1"
           autosize="0"
           showgotobar="0" showcaptioning="0" autostart="1" autorewind="0"
           animationatstart="0" transparentatstart="0" allowscan="1"
           enablecontextmenu="1" clicktoplay="0"
           defaultframe="datawindow" invokeurls="0">
          </embed>
</object><FORM NAME="stpw">
歌曲进度(HS):
          <INPUT Name="time" TYPE="text" size="8">
<input type="BUTTON" name="ssbutton" value="播放" onClick="startstop();">
<br>
</FORM>
<?
//循环打印
for ($i=0;$i<$tmp;$i++) {?>
<div id="s<?=$i?>" style="font-size:12px"><?=preg_replace("/\[.*?\]/i","",$array[$i])? ></div><!--用正则把lrc里的时间替换掉-->
<? }?>
</body>

  评论这张
 
阅读(743)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017