add lrc-format
This commit is contained in:
parent
78ebfc9b74
commit
11d34f3601
@ -12,6 +12,7 @@
|
||||
9. 支持下载歌手 `go run main.go https://music.apple.com/us/artist/taylor-swift/159260351` `--all-album` 自动选择歌手的所有专辑
|
||||
10. 新增[wrapper](https://github.com/zhaarey/wrapper/releases)模式 目前只能linux运行,解密速度超快,基本秒解
|
||||
11. `limit-max`支持限制长度 默认200
|
||||
12. 支持逐词与未同步歌词
|
||||
|
||||
本项目仅支持ALAC和Atmos
|
||||
- `alac (audio-alac-stereo)`
|
||||
|
@ -1,6 +1,7 @@
|
||||
media-user-token: "your-media-user-token"
|
||||
embed-lrc: true
|
||||
save-lrc-file: false
|
||||
lrc-format: "lyrics" #lyrics syllable-lyrics
|
||||
save-artist-cover: false
|
||||
save-animated-artwork: false # If enabled, requires ffmpeg
|
||||
emby-animated-artwork: false # If enabled, requires ffmpeg
|
||||
|
87
main.go
87
main.go
@ -44,6 +44,7 @@ var artist_select = false
|
||||
type Config struct {
|
||||
MediaUserToken string `yaml:"media-user-token"`
|
||||
SaveLrcFile bool `yaml:"save-lrc-file"`
|
||||
LrcFormat string `yaml:"lrc-format"`
|
||||
SaveAnimatedArtwork bool `yaml:"save-animated-artwork"`
|
||||
EmbyAnimatedArtwork bool `yaml:"emby-animated-artwork"`
|
||||
EmbedLrc bool `yaml:"embed-lrc"`
|
||||
@ -1258,7 +1259,7 @@ func getMeta(albumId string, token string, storefront string) (*AutoGenerated, e
|
||||
|
||||
func getSongLyrics(songId string, storefront string, token string, userToken string) (string, error) {
|
||||
req, err := http.NewRequest("GET",
|
||||
fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/songs/%s/lyrics", storefront, songId), nil)
|
||||
fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/songs/%s/%s", storefront, songId, config.LrcFormat), nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -1826,13 +1827,95 @@ func main() {
|
||||
fmt.Printf("======= Completed %d/%d ###### %d errors!! =======\n", oktrackNum, trackTotalnum, trackTotalnum-oktrackNum)
|
||||
}
|
||||
|
||||
func conventTTMLToLRC(ttml string) (string, error) {
|
||||
func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
||||
parsedTTML := etree.NewDocument()
|
||||
err := parsedTTML.ReadFromString(ttml)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var lrcLines []string
|
||||
parseTime := func(timeValue string) (string, error) {
|
||||
var h, m, s, ms int
|
||||
if strings.Contains(timeValue, ":") {
|
||||
_, err = fmt.Sscanf(timeValue, "%d:%d:%d.%d", &h, &m, &s, &ms)
|
||||
if err != nil {
|
||||
_, err = fmt.Sscanf(timeValue, "%d:%d.%d", &m, &s, &ms)
|
||||
h = 0
|
||||
}
|
||||
} else {
|
||||
_, err = fmt.Sscanf(timeValue, "%d.%d", &s, &ms)
|
||||
h, m = 0, 0
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m += h * 60
|
||||
ms = ms / 10
|
||||
return fmt.Sprintf("[%02d:%02d.%02d]", m, s, ms), nil
|
||||
}
|
||||
for _, div := range parsedTTML.FindElement("tt").FindElement("body").FindElements("div") {
|
||||
for _, item := range div.ChildElements() {
|
||||
var lrcSyllables []string
|
||||
for _, lyric := range item.ChildElements() {
|
||||
if lyric.SelectAttr("begin") == nil {
|
||||
continue
|
||||
}
|
||||
beginTime, err := parseTime(lyric.SelectAttr("begin").Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var text string
|
||||
if lyric.SelectAttr("text") == nil {
|
||||
var textTmp []string
|
||||
for _, span := range lyric.Child {
|
||||
if _, ok := span.(*etree.CharData); ok {
|
||||
textTmp = append(textTmp, span.(*etree.CharData).Data)
|
||||
} else {
|
||||
textTmp = append(textTmp, span.(*etree.Element).Text())
|
||||
}
|
||||
}
|
||||
text = strings.Join(textTmp, "")
|
||||
} else {
|
||||
text = lyric.SelectAttr("text").Value
|
||||
}
|
||||
lrcSyllables = append(lrcSyllables, fmt.Sprintf("%s%s", beginTime, text))
|
||||
}
|
||||
endTime, err := parseTime(item.SelectAttr("end").Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
lrcLines = append(lrcLines, strings.Join(lrcSyllables, "")+endTime)
|
||||
}
|
||||
}
|
||||
return strings.Join(lrcLines, "\n"), nil
|
||||
}
|
||||
|
||||
func conventTTMLToLRC(ttml string) (string, error) {
|
||||
parsedTTML := etree.NewDocument()
|
||||
err := parsedTTML.ReadFromString(ttml)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var lrcLines []string
|
||||
timingAttr := parsedTTML.FindElement("tt").SelectAttr("itunes:timing")
|
||||
if timingAttr != nil {
|
||||
if timingAttr.Value == "Word" {
|
||||
lrc, err := conventSyllableTTMLToLRC(ttml)
|
||||
return lrc, err
|
||||
}
|
||||
if timingAttr.Value == "None" {
|
||||
for _, p := range parsedTTML.FindElements("//p") {
|
||||
line := p.Text()
|
||||
line = strings.TrimSpace(line)
|
||||
if line != "" {
|
||||
lrcLines = append(lrcLines, line)
|
||||
}
|
||||
}
|
||||
return strings.Join(lrcLines, "\n"), nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range parsedTTML.FindElement("tt").FindElement("body").ChildElements() {
|
||||
for _, lyric := range item.ChildElements() {
|
||||
var h, m, s, ms int
|
||||
|
Loading…
x
Reference in New Issue
Block a user