Fork me on GitHub

lrc歌词文件格式

 

一、lrc文件有什么作用

lrc文件就是一个文本文件,用来记录歌曲的歌词信息,使得播放歌曲时能够让歌词与声音同步显示,类似于电影字幕那种效果。

心情很丧时我们会听首歌陶冶一下情操,不知你是否注意过音乐播放软件播放音乐时歌词信息,这是酷我音乐的歌词播放界面:

 image

当前正在播放的这一句歌词会被高亮显示,从上面这幅图我们能够看出来,这个歌词文件至少记录了什么时间播放哪一句歌词,这些信息都是放在lrc文件中的,一个lrc文件的格式大致如下:

[al:本歌所在的唱片集]
[ar:演出者-歌手]
[au:歌詞作者-作曲家]
[by:此LRC文件的创建者]
[offset:+/- 以毫秒为单位加快或延後歌詞的播放]
[re:创建此LRC文件的播放器或编辑器]
[ti:歌词(歌曲)的标题]
[ve:程序的版本]
[mm:ss.xx]歌词正文
...

 

[mm:ss.xx]歌词正文,mm表示从开始到现在的分钟数,ss表示从开始到现在的描述,xx表示n*10毫秒,精度是10毫秒。

 

二、LRC解析器

看到这个格式这么简单,便尝试写一个简单的格式解析器,文件结构参考维基百科的定义。

Lrc.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cc11001100.music;
 
import lombok.Data;
 
import java.util.Map;
import java.util.TreeMap;
 
/**
 * @author CC11001100
 */
public class Lrc {
 
    // 唱片集
    private String album;
    // 演唱者
    private String artist;
    // 歌词作者
    private String author;
    // 此LRC文件的创建者
    private String by;
    // 创建此LRC文件的播放器或编辑器
    private String re;
    // 歌词标题
    private String title;
    // 程序的版本
    private String ve;
 
    // 歌词正文
    private Map<String, String> lyric;
 
    public Lrc() {
        lyric = new TreeMap<>();
    }
 
    public String getAlbum() {
        return album;
    }
 
    public void setAlbum(String album) {
        this.album = album;
    }
 
    public String getArtist() {
        return artist;
    }
 
    public void setArtist(String artist) {
        this.artist = artist;
    }
 
    public String getAuthor() {
        return author;
    }
 
    public void setAuthor(String author) {
        this.author = author;
    }
 
    public String getBy() {
        return by;
    }
 
    public void setBy(String by) {
        this.by = by;
    }
 
    public String getRe() {
        return re;
    }
 
    public void setRe(String re) {
        this.re = re;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getVe() {
        return ve;
    }
 
    public void setVe(String ve) {
        this.ve = ve;
    }
 
    public Map<String, String> getLyric() {
        return lyric;
    }
 
    public void setLyric(Map<String, String> lyric) {
        this.lyric = lyric;
    }
}

LrcParser.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package cc11001100.music;
 
import cc11001100.acl.ip.IpAcl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
 
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
 
import static com.alibaba.fastjson.JSON.toJSONString;
 
/**
 * 用于解析LRC歌词
 *
 * @author CC11001100
 */
public class LrcParser {
 
    public static Lrc parse(List<String> lineList) {
        Lrc lrc = new Lrc();
        for (String line : lineList) {
            if (StringUtils.isBlank(line)) {
                continue;
            }
            line = line.toLowerCase();
            // 唱片集
            if (line.startsWith("[al:")) {
                lrc.setAlbum(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[ar:")) {
                // 演唱者
                lrc.setArtist(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[au:")) {
                // 歌词作者
                lrc.setAuthor(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[by:")) {
                // LRC制作者
                lrc.setBy(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[re:")) {
                // 此LRC文件的创建者或编辑器
                lrc.setRe(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[ti:")) {
                // 歌词标题
                lrc.setTitle(line.substring(4, line.length() - 1));
            } else if (line.startsWith("[ve:")) {
                // 程序的版本
                lrc.setVe(line.substring(4, line.length() - 1));
            if (line.startsWith("[ver:")) {
                // 程序的版本
                lrc.setVe(line.substring(5, line.length() - 1));
            } else {
                int delimiterIndex = line.indexOf("]");
                String time = line.substring(1, delimiterIndex);
                String lrcContent = line.substring(delimiterIndex + 1);
                lrc.getLyric().put(time, lrcContent);
            }
        }
        return lrc;
    }
 
    public static void main(String[] args) throws IOException {
 
        List<String> lineList = FileUtils.readLines(new File("H:/KwDownload/Lyric/陈鸿宇-理想三旬.lrc"), "GBK");
        Lrc lrc = parse(lineList);
        System.out.println(toJSONString(lrc, SerializerFeature.PrettyFormat));
 
    }
 
}

 

相关资料:
1. LRC格式 - 维基百科

 

.

posted @   CC11001100  阅读(6426)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2017-11-11 Linux命令之md5sum
点击右上角即可分享
微信分享提示