QQ音乐的QRC歌词分析

今天Naville也依旧在坑QQ音乐的歌词。Dump出的歌词是QRC格式的,也就是QQ音乐自己的格式,这个格式比起传统的LRC多了一个功能(至少目前我发现的):可以让高亮准确地跟着歌词走,而不是一次亮一整句,或者以平均速度高亮完一句歌词。

那么这里就以Naville发给我的一个Sample作为例子吧。


QRC的大致样子如下,

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<QrcInfos>
<QrcHeadInfo SaveTime="1400298876" Version="100"/>
<LyricInfo LyricCount="1">
<Lyric_1 LyricType="1" LyricContent="[ti:A Sky Full of Stars]
[ar:Coldplay]
[al:Ghost Stories]
[by:]
[offset:0]
[750,1330]A (750,180)Sky (930,180)Full (1110,150)of (1260,180)Stars (1440,140)- (1580,160)Coldplay(1740,340)
[17598,1070]Cause (17598,230)you're (17828,210)a (18038,250)sky,(18288,380)
[19488,2660]cause (19488,210)you're (19698,260)a (19958,200)sky (20158,1130)full (21288,220)of (21508,260)stars(21768,380)
[25128,2850]I'm (25128,270)gonna (25398,350)give (25748,550)you (27028,220)my (27248,350)heart(27598,380)
[33028,1180]Cause (33028,180)you're (33208,210)a (33418,230)sky,(33648,560)
[34808,2710]cause (34808,430)you're (35238,190)a (35428,460)sky (35888,820)full (36708,190)of (36898,230)stars(37128,390)
[40858,2499]Cause (40858,180)you (41038,190)light (41228,1270)up (42498,200)the (42698,200)path(42898,459)
[48257,4709]I (48257,260)don't (48517,260)care, (48777,460)go (50017,240)on (50257,360)and (50617,220)tear (50837,950)me (51787,520)apart(52307,659)
[55896,2909]I (55896,300)don't (56196,250)care (56446,899)if (57345,390)you (57735,270)do(58005,800)
[63625,1020]Cause (63625,200)in (63825,220)a (64045,210)sky,(64255,390)
[65585,2580]cause (65585,200)in (65785,190)a (65975,180)sky (66155,630)full (67405,190)of (67595,200)stars(67795,370)
[69215,1130]I (69215,200)think (69415,160)I (69575,170)saw (69745,260)you(70005,340)
[102247,1010]Cause (102247,240)you're (102487,210)a (102697,220)sky,(102917,340)
[103967,2550]cause (103967,260)you're (104227,190)a (104417,210)sky (104627,330)full (105677,230)of (105907,230)stars(106137,380)
[109717,3710]I (109717,210)want (109927,210)to (110137,200)die (110337,360)in (111527,210)your (111737,220)arms, (111957,440)arms(113107,320)
[117507,4609]Cause (117507,220)you (117727,190)get (117917,190)lighter (118107,350)the (119307,220)more (119527,1090)it (120617,510)gets (121127,390)dark(121517,599)
[125096,2730]I'm (125096,200)going (125296,240)to (125536,340)give (125876,1000)you (126876,200)my (127076,250)heart(127326,500)
[131126,2840]And (131126,450)I (131576,1180)don't (132756,470)care,(133226,740)
[134666,2600]go (134666,210)on (134876,260)and (135136,190)tear (135326,1150)me (136476,370)apart(136846,420)
[140456,2580]And (140456,210)I (140666,290)don't (140956,200)care (141156,690)if (141846,450)you (142296,210)do(142506,530)
[148266,960]Cause (148266,190)in (148456,210)a (148666,190)sky,(148856,370)
[150026,2890]cause (150026,220)in (150246,180)a (150426,200)sky (150626,1220)full (151846,210)of (152056,220)stars(152276,640)
[153956,3280]I (153956,190)think (154146,200)I (154346,340)see (154686,290)you(154976,2260)
[161426,1989]I (161426,210)think (161636,170)I (161806,570)see (162376,460)you(162836,579)
[217294,1340]Because (217294,300)you're (217594,250)a (217844,330)sky,(218174,460)
[219324,2580]you're (219324,240)a (219564,240)sky (219804,1130)full (220934,220)of (221154,280)stars(221434,470)
[222474,1740]Such (222474,260)a (222734,260)Heavenly (222994,570)view(223564,650)
[229794,3499]You're (229794,210)such (230004,200)a (230204,220)Heavenly (230424,709)view(231133,2160)
"/>
</LyricInfo>
</QrcInfos>

 
简单来说就是一份XML文档,根节点是<QrcInfos>

子节点<QrcHeadInfo SaveTime="1400298876" Version="100"/>记录了这份QRC歌词的保存时间和版本号,这里的版本应该是指当前QRC的版本,而非歌词内容的版本。

接下来的<LyricInfo LyricCount="1">记录了这份QRC里面保存的歌词数量。

然后根据歌词数量,从1开始,对应歌词的节点名为<Lyric_$i
其中$i为对应的index。

比如,第一个歌词就应该是:
<Lyric_1 LyricType="1" LyricContent="Lyric Content ... "/>

LyricContent 前面部分和普通的LRC一样,但是在时间轴部分用了新的格式。

以第一句为例,

[750,1330]A (750,180)Sky (930,180)Full (1110,150)of (1260,180)Stars (1440,140)- (1580,160)Coldplay(1740,340)

即形如:
[time_1,duration_1] Word 1 (time_2, duration_2) Word 2 (time_3, duration_3) Word 3 ...

那么这里的time_1是以微秒为单位的,从音乐开始(00:00.00)到这一句的时间

duration_1是这一整句歌词的持续时间, 1330 = 180 + 180 + 150 + 180 + 140 + 160 + 340;

剩余的time_2, time_3 ... 也是从音乐开始(00:00.00)到这一句的时间,不过只有以[]开头的才是一句歌词的开始。

duration_2, duration_3 ... 都是紧跟在后面的Word的持续时间。

通过解析这些标记,QQ音乐便可以实现高亮进度准确地跟着歌词。