首页logo
  •  

jonllen

金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。

个人档案

jonllen
心情闪存 | 给他留言
妮称:jonllen
来自:中国. 湖南. 湘潭
简述:金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。
博客日历

Flex播放器同步显示歌词

分类:Flex

在听完S.H.E的你最近还吗不下一百遍,终于搞好了播放器同步显示歌词这一功能。这是继上一篇Flex播放器(实现播放、缓冲进度条和音频曲线显示)后的一扩展功能,本例是实现对lrc文本格式的歌词进行解析显示,并把当前播放歌词一行文本进行高亮显示。

播放歌曲时要同步显示歌词,首先必须要能解析出lrc格式的歌词文本,之前我还准备直接在网上匹配下载对应歌词,打开我机器的千千静音在线匹配歌词,然后用HTTPAnalyzerStdV监视所有的http请求,发现它是请求这个ttlrcct.qianqian.com网站下载歌词,本来还是直接套用千千静音服务器下载歌词,但是它的url参数全部加密了。后来又看了下酷狗音乐,它里面下载歌词我都监视不请求,考虑到就算我能在线找到下载歌词的url地址,flash里发送远程请求也会有安全杀箱问题,所以最终放弃直接在网络上下载歌词的办法,还是全部上传到我网站上去。lrc歌词其实就是一个文本格式的文件,在Flex里面我们可以使用URLLoader去加载,代码如下:

/加载歌词
var lrcUrl :
String = xml.item[currIndex].lrc;
if ( lrcUrl!=null && lrcUrl!="")
{
var lrc:URLLoader
= new URLLoader();
//lrc.dataFormat = URLLoaderDataFormat.VARIABLES;
lrc.load(
new URLRequest(lrcUrl));
lrc.addEventListener(Event.COMPLETE,LRC_Complete);
lrc.addEventListener(IOErrorEvent.IO_ERROR,LRC_IOError);
}
lrcArr
= null;
outPutLRCString
= "";
startIndexOf
= 0;
txtLrc.text
= "";

然后在加载完成的事件里,我们能得到lrc文本字符串,这时候我们需要对字符串进行处理,把它转换成一个Array数组,函数方法如下:

public function getLRCArray(lrc:String):Array {
var lrcArr:
Array=new Array;

lrc
+= "\r";

for (var i:int = 0; i < lrc.length; i++) {
var
time:Number = 0;
if (lrc.charAt(i) == ":") {
time = Number(lrc.slice(i - 2, i)) * 60 + Number(lrc.slice(i + 1, i + 3));
if (String(time) != "NaN") {
var j:uint
= 0;
var startIndex:uint
= 0;
var endIndex:uint
= 0;
do {
j
++;
if (lrc.charAt(i + j) == "]") {
startIndex
= i + j + 1;
}
}
while (i + j < lrc.indexOf("\r", i))

endIndex
= lrc.indexOf("\r", i);

if(startIndex!=0&&endIndex!=0){
lrcArr.push([
time,lrc.slice(startIndex, endIndex)]);
}
}
}
}

return lrcArr;
}

解析歌词返回的Array数组为多围数组,数组里的每一项是为一个二围数组,item[0]为当前秒数,item[1]为该秒显示的歌词(句),比如item[0]=歌曲名:你最近还好吗、item[5]=演唱:S.H.E,就是代表第0秒显示歌曲名:你最近还好吗,而从第5秒起则显示演唱:S.H.E,这样通过getLRCArray方法就能得到歌曲所有的时间段显示的歌词拉。本例中把所有歌词放在一个editable="false"不可修改的mx:TextArea文本域内。

歌词同步显示的问题

歌词能全部加载显示了,问题是怎么随着歌曲的播放而高亮显示当前行歌词呢?不过还好Flex提供一个TextRange能对TextArea内文本进行选择性的处理,你只需要设置beginIndex和endIndex就能自动匹配到TextArea中间区域的文本,我这里只是简单的改变了一下颜色,不过我们从TextArea中找某一个句歌词索引的时候需要注意歌词有很多是重复的,所以我们需要用一个变量保存当前歌词播放位置索引startIndexOf,以确保我们高亮选择到的歌词是正确的。同时将TextArea滚动条设置到对应的高度,主要的代码如下:

//同步显示歌词
if( lrcArr!=null && lrcArr.length > 0)
{
var sec:Number
=int(channel.position/1000);
for(var j:int=0;j<lrcArr.length;j++){
if(lrcArr[j][0]==sec){
var currentLrc :
String = lrcArr[j][1];
if( currentLrc != this.currLrc.text)
{
currLrc.text
= currentLrc;
//高亮显示,先清空之前高亮部分
var tr : TextRange
= new TextRange(txtLrc);
tr.color
= this.getStyle("color");

var beginIndex :
int = this.outPutLRCString.indexOf(currentLrc,startIndexOf);
startIndexOf
+= currentLrc.length;
var endIndex :
int = beginIndex + currentLrc.length;
tr.beginIndex
= beginIndex;
tr.endIndex
= endIndex;
if ( tr.text != "" )
{
tr.color
= "yellow";
}
//设置滚动条位置
this.txtLrc.verticalScrollPosition
=j*this.txtLrc.maxVerticalScrollPosition/lrcArr.length;
if( lrcArr.length - j <= 5 ) this.txtLrc.verticalScrollPosition = this.txtLrc.maxVerticalScrollPosition;
}
break;
}
}

}

上面sec是当前歌曲播放的时间秒数,然后循环换数组判断rcArr[j][0]跟当前sec比较,秒数一致才显示对应歌词,一段歌词可能在好几秒内都不会变的,同时根据当前歌词的数组索引位置设置TextArea滚动条位置,让当前正在播放的歌词在中间显示。

效果请到移步我的Flex博客网页:/Flex/bin-debug/Index.html

标签:Flex
  • posted@ 2010-01-03 23:17
  • update@ 2010-01-04 00:26:38
  • 阅读(12687)
  • 评论(8)

相关文章

评论
1楼 小杰 2010-01-04 01:39:39
Flex牛人,厉害厉害贩
回复:我也是刚入门学习Flex,很多flash基本的动画都不会做... 只会拖一些Flex的mx组件用~(2010-01-04 09:09:24)
2楼 苏扬 2010-01-04 09:50:51
我想弄一个PJ得插件,那才实在 嘿嘿
回复::)弱弱的问题,PJ什么插件?(2010-01-04 12:40:47)
3楼 漠然 2010-01-04 10:33:46
对于认识16个英文字母的漠然来说,无论写任何代码的,都是高高手!
回复:西西~`(2010-01-04 12:38:45)
4楼 低调VS飞翔 2010-01-04 18:16:24
代码真的要这么写吗?
可以不可以写密集点。
回复:写密集点???(2010-01-04 20:49:08)
5楼 老七 2010-01-05 16:44:58
联盟审核通过。。
6楼 flex爱好者 2010-04-06 20:45:19
你好!又是我啊,非常感谢你发给我的song.xml,现在已经加载成功了。但是还是不是很明白如何同步歌词?txt可以按照播放同步?可以发一份最终的源码给我吗?谢啦~~hongyizung@vip.qq.com
回复:我歌词里的内容就是LRC歌词文件的格式,之所以用txt文件后缀名是因为我的空间请求访问不了lrc结尾的后缀文件,我在文章里已经写得很清楚了,通过getLRCArray方法把歌词文本转化为了一句句的歌词数组。(2010-04-07 10:02:04)
7楼 cugfjm 2010-08-31 04:03:01
做得太好了,能发一份源码吗
8楼 cugfjm 2010-08-31 04:04:11
奥,我的邮箱为475127495@qq.com
发表评论
*必填
回复通知我
*必填

博文推荐