Flash AS制作LRC歌词同步的详细教程
一、准备工作
既然要制作歌词同步程序,首先要准备一首歌,我们就以“周杰伦-青花瓷”为例。首先要下载这首“青花瓷.mp3”,保存为“C:\My Player\Music\青花瓷.mp3”。还要下载青花瓷的 LRC 文件,大家可以到网上下载(地址见附录),将文本内容保存为“C:\My Player\LRC\青花瓷.lrc”。我们的程序(类和FLA)则保存在“C:\My Player\”文件夹下。
青花瓷.lrc 文件:
--------------------------------------------------------------------------------
[ti:青花瓷]
[ar:周杰伦]
[al:我很忙]
[by:张琪]
[00:00.00]发送短信18到291199下载该歌曲到手机
[00:01.11]青花瓷
[03:36.49]
[00:21.39]素眉勾勒秋千话北风龙转丹
[00:26.08]屏层鸟绘的牡丹一如你梳妆
[00:30.46]黯然腾香透过窗心事我了然
[00:34.93]宣纸上皱边直尺各一半
[00:39.49]油色渲染侍女图因为被失藏
[00:43.83]而你嫣然的一笑如含苞待放
[00:48.30]你的美一缕飘散
[00:50.77]去到我去不了的地方
[02:23.97][00:55.77]
[03:01.92][02:25.63][00:56.90]天正在等烟雨
[03:03.57][02:27.91][00:58.99]而我在等你
[03:05.92][02:30.44][01:00.93]炊烟袅袅升起
[03:07.76][02:32.25][01:03.49]隔江千万里
[03:10.36][02:34.85][01:05.84]在平地书刻你房间上的飘影
[03:14.67][02:38.73][01:09.87]就当我为遇见你伏笔
[03:18.83][02:43.35][01:14.34]天正在等烟雨
[03:21.20][02:45.60][01:16.68]而我在等你
[03:23.71][02:48.01][01:18.99]月色被打捞起
[03:25.74][02:50.10][01:21.18]掩盖了结局
[03:28.33][02:52.54][01:23.72]如传世的青花瓷在独自美丽
[03:32.30][02:56.67][01:27.65]你眼的笑意
[01:50.25]色白花青的景已跃然于碗底
[01:54.69]临摹宋体落款时却惦记着你
[01:59.22]你隐藏在药效里一千年的秘密
[02:03.75]急溪里犹如羞花沾落地
[02:08.32]林外芭蕉 惹咒语
[02:10.57]梦幻的铜绿
[02:12.84]而我路过那江南小镇的等你
[02:17.19]在泼墨山水画里
[02:19.75]你从墨色深处被隐去
--------------------------------------------------------------------------------
大家也可以把这个文本内容复制下来,然后在“C:\My Player\LRC\”下创建一个文本文档,将内容粘贴上去,再将文档保存为“青花瓷.lrc”,注意扩展名是“.lrc”。
二、LRC 内容分析
准备工作完成了,下面分析一下这个 LRC 文件。之所以叫 LRC ,是因为它是 Lyric (歌词) 的缩写。这种格式真是一目了然,前面“[ ]”中的数字表示其后歌词的开始时间。例如,“[01:50.25]色白花青的景已跃然于碗底”表示在1分50.25秒时,歌词内容是“色白花青的景已跃然于碗底”。
还有一种形式是“[03:01.92][02:25.63][00:56.90]天正在等烟雨”这种形式常用于赋格部分(俗称:歌曲的高潮部分),它表示在 03:01.92, 02:25.63, 00:56.90 时的歌词都是“天正在等烟雨”。由于这种形式的存在,使后面的编程稍显复杂,不过没关系,凭借各位的聪明智**
四、LRC 的读取与存储转换(使用文档类设计)
1.读取 LRC 文件,这一步非常简单与读取普通的文本文件是一样的;
CODE:
public function LRCPlayer() {
--------------------------------------------------------------------------------
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
}
private function LoadFinish(evt:Event):void {
trace(evt.target.data);
}
2.将读取的 LRC 数据按行分割( "\n" 为换行符),数组的每一个元素代表 LRC 的一行内容;
CODE:
function LoadFinish(evt:Event):void {
--------------------------------------------------------------------------------
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
trace(listarray);
}
3.在数组中提取每一行的时间及歌词,解决单时间序列的问题;(注意!此段代码只作讲解,不以应用)
LRC 内容如下:
QUOTE:
[00:43.83]而你嫣然的一笑如含苞待放代码如下:
[00:48.30]你的美一缕飘散
[00:50.77]去到我去不了的地方
[03:01.92]天正在等烟雨
[03:03.57]而我在等你
[03:05.92]炊烟袅袅升起
[03:07.76]隔江千万里
CODE:
function LoadFinish(evt:Event):void {
输出结果:
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
for (var i=0; i
//提取每行内容,用变量 info 保存
var lyric:String=info.substr(10);
//将歌词内容提取到 lyric 变量中
var ctime:String =info.substr(0,10);
//提取时间序列字串
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
//将时间字串转换为计算机可读取的时间
var obj:Object=new Object();
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
//将时间与歌词保存到一个 Object 中,并压入LRCarray 数组
trace(obj.timer,obj.lyric);
}
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
181920 天正在等烟雨
183570 而我在等你
185920 炊烟袅袅升起
187760 隔江千万里
4.在LRC文件,还有多时间序列的存在,所以单时间序列算法不能满足实际需要,下面就来解决多时间序列问题;
LRC 内容如下:
QUOTE:
[00:43.83]而你嫣然的一笑如含苞待放代码如下:
[00:48.30]你的美一缕飘散
[00:50.77]去到我去不了的地方
[03:01.92][02:25.63][00:56.90]天正在等烟雨
[03:03.57][02:27.91][00:58.99]而我在等你
[03:05.92][02:30.44][01:00.93]炊烟袅袅升起
[03:07.76][02:32.25][01:03.49]隔江千万里
CODE:
function LoadFinish(evt:Event):void {
输出结果:
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
var reg:RegExp=/\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\]/g;
//建立正则表达式,范围:[00:00.00]~[59:59.99]
for (var i=0; i
//提取每行内容,用变量 info 保存
var len:int=info.match(reg).length;
//该行拥有时间序列的个数
var timeAry:Array=info.match(reg);
//将匹配的时间序列保存到 timeAry 数组中
var lyric:String=info.substr(len*10);
//根据每个时间序列占10个字符,找出歌词内容的起点
//将歌词提取到 lyric 变量中
for (var k:int=0; k
var ctime:String=timeAry[k];
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
trace(obj.timer,obj.lyric);
}
//将时间序列转换为毫秒并与歌词一起保存为一个数组元素
}
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
181920 天正在等烟雨
145630 天正在等烟雨
56900 天正在等烟雨
183570 而我在等你
147910 而我在等你
58990 而我在等你
185920 炊烟袅袅升起
150440 炊烟袅袅升起
60930 炊烟袅袅升起
187760 隔江千万里
152250 隔江千万里
63490 隔江千万里
5.将获得的 LRCarray 数组按起始时间排序,这对于按序读取歌词有重要意义;
CODE:
LRCarray.sort(compare);
结果如下:
private function compare(paraA:Object,paraB:Object):int {
if (paraA.timer>paraB.timer) {
return 1;
}
if (paraA.timer
}
return 0;
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
56900 天正在等烟雨
58990 而我在等你
60930 炊烟袅袅升起
63490 隔江千万里
145630 天正在等烟雨
147910 而我在等你
150440 炊烟袅袅升起
152250 隔江千万里
181920 天正在等烟雨
183570 而我在等你
185920 炊烟袅袅升起
187760 隔江千万里
6.最后,随着音乐的播放,读取播放时间段内的歌词。用当前播放时间与 LRCarray 中的时间相比较,如果当前时间小于 LRCarray.timer 的时间,那么就显示 LRCarray[i-1].lyric 的歌词。为什么要显示 [i-1] 的歌词呢?比如说当前播放到第 500 秒,读取的 LRCarray[20].timer 时间是 400 秒,那么 i 。下一次读取的 LRCarray[21].timer 时间是 700 秒,这时当前播放时间小于读取的这个时间,就说明当前的第 500 秒仍处于 LRCarray[20].timer 的时间范围内。
CODE:
var lrc_txt:TextField=new TextField();
五、全部代码(文档类 LRCPlayer.as):
var LRCarray:Array=new Array();
var sc:SoundChannel;
public function LRCPlayer() {
lrc_txt.width=500;
lrc_txt.selectable=false;
addChild(lrc_txt);
//歌词在文本 lrc_txt 中显示
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
var sound:Sound=new Sound();
sound.load(new URLRequest("Music/青花瓷.mp3"));
sc=sound.play();
//播放声音,并生成 sc 变量,SoundChannel 类的实例
stage.addEventListener(Event.ENTER_FRAME,SoundPlaying);
//实时刷新歌词
}
function SoundPlaying(evt:Event):void {
for (var i=1; i
break;
//找到歌词,跳出循环体
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
//找不到歌词,说明已超出了最后一句的时间,因此显示最后一句歌词
}
}
CODE:
package {
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.text.TextField;
import flash.system.System;
public class LRCPlayer extends Sprite {
var lrc_txt:TextField=new TextField();
var LRCarray:Array=new Array();
var sc:SoundChannel;
public function LRCPlayer() {
System.useCodePage=true;
lrc_txt.width=500;
lrc_txt.selectable=false;
addChild(lrc_txt);
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
var sound:Sound=new Sound();
sound.load(new URLRequest("Music/青花瓷.mp3"));
sc=sound.play();
stage.addEventListener(Event.ENTER_FRAME,SoundPlaying);
}
function SoundPlaying(evt:Event):void {
for (var i=1; i
break;
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
}
}
function LoadFinish(evt:Event):void {
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
var reg:RegExp=/\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\]/g;
for (var i=0; i
var len:int=info.match(reg).length;
var timeAry:Array=info.match(reg);
var lyric:String=info.substr(len*10);
for (var k:int=0; k
var ctime:String=timeAry[k];
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
}
}
LRCarray.sort(compare);
}
private function compare(paraA:Object,paraB:Object):int {
if (paraA.timer>paraB.timer) {
return 1;
}
if (paraA.timer
}
return 0;
}
}
}
六、*无处不在的优化
至此,该程序已经可以顺利执行了,此处只讨论一下优化问题,看不懂可以跳过。
以这段代码为例:
CODE:
function SoundPlaying(evt:Event):void {
如果要进行优化,那么这个 for 循环,应该写成:
for (var i=1; i
break;
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
}
}
CODE: CODE: CODE:
for (var i=1,j=LRCarray.length; i
if (sc.position
function SoundPlaying(evt:Event):void {
在我们的文档类中还有几个地方用到了 for 循环,请大家按照上述方法自行优化。
var now:Number=sc.position;
for (var i=1,j=LRCarray.length; i
break;
}
lrc_txt.text=LRCarray[j-1].lyric;
}
}
其实,代码优化无处不在,其中的学问不胜枚举,有兴趣的朋友可以到我的博客中看一下关于代码优化的总结贴,见附录。
七、附录
1.LRC 文件下载地址:
http://lrc.bzmtv.com/
http://www.5ilrc.com/
2.至于 MP3 的下载,我想大家比我在行,用百度或酷狗都可以。
3.代码优化总结贴地址:
https://www.jb51.net/flash/actionscript-5898.html
4.整个文件包括(歌曲、歌词、LRCPlayer.as 、FLA 文件)打包下载:
http://www.fs2you.com/zh-cn/files/cf760b0f-01a0-11dd-9174-0014221f3995/
八、结束语
恭喜您坚持到了现在,确实内容比较长,同时也涉及了一些知识点。其实做法肯定不只这一种,所以希望大家多多发挥主观能动性,结合上述内容继续将这个播放程序做大做强。好了,就到这里,再次感谢。
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文地址:/3Dsheji/170356.html