ltc/lrc.go

129 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ltc
import (
"regexp"
"strconv"
"strings"
"github.com/Hami-Lemon/ltc/glist"
)
type LRCNode struct {
//歌词出现的时间,单位毫秒
time int
//歌词内容
content string
}
type LRC struct {
//歌曲名
Title string
//歌手名
Artist string
//专辑名
Album string
//歌词作者
Author string
//歌词列表
LrcList glist.Queue[*LRCNode]
}
func ParseLRC(src string) *LRC {
if src == "" {
return nil
}
//标准的LRC文件为一行一句歌词
lyrics := strings.Split(src, "\n")
//标识标签的正则 [ar:A-SOUL]形式
infoRegx := regexp.MustCompile(`^\[([a-z]+):([\s\S]*)]`)
lrc := &LRC{LrcList: glist.NewLinkedList[*LRCNode]()}
//解析标识信息
for {
if len(lyrics) == 0 {
break
}
l := lyrics[0]
//根据正则表达式进行匹配
info := infoRegx.FindStringSubmatch(l)
//标识信息位于歌词信息前面,当出现未匹配成功时,即可退出循环
if info != nil {
//info 中为匹配成功的字符串和 子组合(正则表达式中括号包裹的部分)
//例如,对于标识信息:[ar:A-SOUL]info中的数据为[[ar:A-SOUL], ar, A-SOUL]
key := info[1]
switch key {
case "ar":
//歌手名
if len(info) == 3 {
lrc.Artist = info[2]
}
case "ti":
//歌曲名
if len(info) == 3 {
lrc.Title = info[2]
}
case "al":
//专辑名
if len(info) == 3 {
lrc.Album = info[2]
}
case "by":
//歌词作者
if len(info) == 3 {
lrc.Author = info[2]
}
}
lyrics = lyrics[1:]
} else {
break
}
}
//歌词信息的正则,"[00:10.222]超级的敏感"或“[00:10:222]超级的敏感”或“[00:10]超级的敏感”或“[00:10.22]超级的敏感”或“[00:10:22]超级的敏感”
lyricRegx := regexp.MustCompile(`\[(\d\d):(\d\d)([.:]\d{2,3})?]([\s\S]+)`)
for _, l := range lyrics {
content := lyricRegx.FindStringSubmatch(l)
if content != nil {
node := SplitLyric(content[1:])
if node != nil {
lrc.LrcList.PushBack(node)
}
}
}
return lrc
}
// SplitLyric 对分割出来的歌词信息进行解析
func SplitLyric(src []string) *LRCNode {
minute, err := strconv.Atoi(src[0])
second, err := strconv.Atoi(src[1])
if err != nil {
panic("错误的时间格式:" + strings.Join(src, " "))
return nil
}
millisecond, content := 0, ""
_len := len(src)
if _len == 3 {
//歌词信息没有毫秒值
content = src[2]
} else if _len == 4 {
content = src[3]
//毫秒字符串的第一个字符是 "." 或 ":",需要去掉
ms := src[2][1:]
millisecond, err = strconv.Atoi(ms)
//QQ音乐歌词文件中毫秒值只有两位需要特殊处理一下
if len(ms) == 2 {
millisecond *= 10
}
if err != nil {
panic("错误的时间格式:" + strings.Join(src, " "))
return nil
}
}
lrcNode := &LRCNode{
time: time2Millisecond(minute, second, millisecond),
content: strings.TrimSpace(content), //去掉前后的空格
}
return lrcNode
}