·您当前的位置:主页 > 技术教程 > Html5技术 >

[html5]在html5下做音频Audio标签实现歌词同步效果的音乐播放器

时间:2017-01-24 09:38酷播
本文介绍在html5下做现歌词同步效果的音乐播放器,附详细的步骤与代码参考,很方便理解。原文作者:刘哇勇,来自cnblogs.com文章。

HTML5草案里面其实有原生的字幕标签(<track> Tag)的,但使用的是vtt格式的文件,非常规的字幕(.sub, .srt)或歌词文件(.lrc)。

用法如下(代码来自W3School):

  1. <video width="320" height="240" controls> 
  2.   <source src="forrest_gump.mp4" type="video/mp4"> 
  3.   <source src="forrest_gump.ogg" type="video/ogg"> 
  4.   <track src="subtitles_en.vtt" kind="subtitles" srclang="en" label="English"> 
  5.   <track src="subtitles_no.vtt" kind="subtitles" srclang="no" label="Norwegian"> 
  6. </video> 

但遗憾的是,使用起来还有不便之处。一是浏览器支持情况不太理想,连强大的FireFox(目前28.0)都还没支持,这你敢信!?。二是格式不兼容现有字幕或歌词文件,至少得需要个转换工具吧。

所以在它流行起来之前,考虑另外的实现还是有必要的。

效果预览

效果预览页面:http://wayou.github.io/selected/

如果你网速流畅的话,尽情欣赏我精选的这些歌曲吧(不时更新),只是别忘了star,也可以fork后添加自己喜欢的歌曲。

项目GitHub地址:https://github.com/wayou/selected

具体实现可以前往项目的GitHub页面下载代码进行查看,下面介绍思路和简单的实现。

歌词文件的格式

实现之前,当然得了解一下歌词文件的格式了。常规歌词文件的格式基本是一句一行,每行由两部分组成,前面是中括号括起来的时间轴,后面紧跟歌词,像下面这样:

  1. [ar:文筱芮] 
  2. [by:airplay] 
  3. [00:00.00]那个 
  4. [00:03.00]作词:文筱芮 作曲:文筱芮 
  5. [00:06.00]编曲:于韵非 
  6. [00:09.00]制作人:胡海泉 秦天 
  7. [00:12.00]演唱:文筱芮 

这样挺有规律的,用正则可以很方便地将时间与歌词提取分离。

但凡事得多个心眼啊。事后发生的事情证明这句话有多正确。我在整理歌词时还发现了另外一种形式,像下面这样:

  1. [ar:庭竹] 
  2. [al:爱的九宫格] 
  3. [by:airplay] 
  4. [00:00.17]庭竹 - 公主的天堂 
  5. [00:05.40]作曲:陈嘉唯、Skot Suyama 陶山、庭竹 
  6. [00:07.33]作词:庭竹 
  7. [00:15.59]风铃的音谱 在耳边打转 
  8. [00:18.62]城堡里 公主也摆脱了黑暗的囚禁 
  9. [00:22.82]她一点点地 无声悄悄地慢慢长大 
  10. [00:26.36]期待着 深锁木门后的世界 
  11. [01:38.72][00:29.76] 
  12. [01:51.48][00:30.32]树上 小鸟的轻响 在身边打转 
  13. [01:55.35][00:34.09]公主已 忘记木制衣橱背后的惆怅 
  14. [01:59.65][00:38.35]她跳舞唱歌天真无邪地寻找属于自己的光亮和快乐 
  15. [02:06.98][00:45.76] 
  16. [02:07.41][00:46.06]树叶一层层拨开了伪装 
  17. [02:11.29][00:50.25]彩虹一步步露出美丽脸庞 无限的光亮 

这种形式的歌词把歌词内容相同但时间不同的部分合并,节省了篇幅。

所以,现在知道的歌词其实有两种写法了,不过都还算规律,用正则可以搞定,只是对于第二种,处理时得将时间再次分割。

具体思路

  1. 首先将LRC文件读取为文本
  2. String.prototype.split('\n');将整个文本以换行符为单位分隔成一行一行的文本,保存到一个数组中
  3. 然后将开头部分不属于歌词的文本去掉,得到只有时间与歌词的干净文件
  4. 对于每一行,匹配出时间与文字,分别存入数组[time,text],然后将每行得到的这样的数组存入一个大的数组[[time,text],[time,text]…]
  5. 利用Audio标签的ontimeupdate事件,不断比较当然播放时间audio.currentTime与数组中每个元素中时间,如果当前时间大于某个歌词中的时间,则显示该歌词

文件读取

在具体处理歌词前,需要解决一个问题就是如何把歌词文件读取到代码中。对于文件读取,JavaScript中可以用FileReader,但它需要手动选择文件,也就是你得在页面放一个file类型的input或者实现文件拖拽操作,显示不可能让用户听歌的时候自己去找歌词然后上传,多麻烦。但JavaScript是没有办法操作本地文件的能力的,那就只能通过XMLHttpRequest(Ajax)发起一个到服务器的请求来获得文件了,这样一来,我们的程序就必需得运程在服务器上面。所以当你从GitHub下载了本文的源码后是无法直接运行的,请挂到本地服务器上观看效果

下面展示了如何发起一个Ajax请求来获得歌词文件。

  1. function getLyric(url) { 
  2.     //cuplayer.com提示建立一个XMLHttpRequest请求 
  3.     var request = new XMLHttpRequest(); 
  4.     //配置, url为歌词地址,比如:'./content/songs/foo.lrc' 
  5.     request.open('GET', url, true); 
  6.     //因为我们需要的歌词是纯文本形式的,所以设置返回类型为文本 
  7.     request.responseType = 'text'
  8.     //一旦请求成功,但得到了想要的歌词了 
  9.     request.onload = function() { 
  10.         //这里获得歌词文件 
  11.         var lyric = request.response; 
  12.     }; 
  13.     //向服务器发送请求 
  14.     request.send(); 

微信付费直播
酷播云免费在线视频整体解决方案
参与开学季云视频优惠,拿GET2017教育科技大会VIP门票
进入开学季,保利威视推出云视频优惠,云视频套餐、流量超实惠大放“价”就是现在,还可以免费获取GET2017教育科技大会VIP门票哦!