mirror of
https://github.com/zhaarey/apple-music-downloader.git
synced 2025-10-23 15:11:05 +00:00
beta: Get translated lyrics
This commit is contained in:
@@ -16,6 +16,7 @@ type SongLyrics struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Attributes struct {
|
Attributes struct {
|
||||||
Ttml string `json:"ttml"`
|
Ttml string `json:"ttml"`
|
||||||
|
TtmlLocalizations string `json:"ttmlLocalizations"`
|
||||||
PlayParams struct {
|
PlayParams struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
@@ -49,7 +50,7 @@ func Get(storefront, songId, lrcType, language, lrcFormat, token, mediaUserToken
|
|||||||
}
|
}
|
||||||
func getSongLyrics(songId string, storefront string, token string, userToken string, lrcType string, language string) (string, error) {
|
func getSongLyrics(songId string, storefront string, token string, userToken string, lrcType string, language string) (string, error) {
|
||||||
req, err := http.NewRequest("GET",
|
req, err := http.NewRequest("GET",
|
||||||
fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/songs/%s/%s?l=%s", storefront, songId, lrcType, language), nil)
|
fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/songs/%s/%s?l=%s&extend=ttmlLocalizations", storefront, songId, lrcType, language), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,10 @@ func getSongLyrics(songId string, storefront string, token string, userToken str
|
|||||||
obj := new(SongLyrics)
|
obj := new(SongLyrics)
|
||||||
_ = json.NewDecoder(do.Body).Decode(&obj)
|
_ = json.NewDecoder(do.Body).Decode(&obj)
|
||||||
if obj.Data != nil {
|
if obj.Data != nil {
|
||||||
return obj.Data[0].Attributes.Ttml, nil
|
if len(obj.Data[0].Attributes.Ttml) > 0 {
|
||||||
|
return obj.Data[0].Attributes.Ttml, nil
|
||||||
|
}
|
||||||
|
return obj.Data[0].Attributes.TtmlLocalizations, nil
|
||||||
} else {
|
} else {
|
||||||
return "", errors.New("failed to get lyrics")
|
return "", errors.New("failed to get lyrics")
|
||||||
}
|
}
|
||||||
@@ -165,7 +169,7 @@ func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
var lrcLines []string
|
var lrcLines []string
|
||||||
parseTime := func(timeValue string, newLine bool) (string, error) {
|
parseTime := func(timeValue string, newLine int) (string, error) {
|
||||||
var h, m, s, ms int
|
var h, m, s, ms int
|
||||||
if strings.Contains(timeValue, ":") {
|
if strings.Contains(timeValue, ":") {
|
||||||
_, err = fmt.Sscanf(timeValue, "%d:%d:%d.%d", &h, &m, &s, &ms)
|
_, err = fmt.Sscanf(timeValue, "%d:%d:%d.%d", &h, &m, &s, &ms)
|
||||||
@@ -182,34 +186,22 @@ func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
|||||||
}
|
}
|
||||||
m += h * 60
|
m += h * 60
|
||||||
ms = ms / 10
|
ms = ms / 10
|
||||||
if newLine {
|
if newLine == 0 {
|
||||||
return fmt.Sprintf("[%02d:%02d.%02d]<%02d:%02d.%02d>", m, s, ms, m, s, ms), nil
|
return fmt.Sprintf("[%02d:%02d.%02d]<%02d:%02d.%02d>", m, s, ms, m, s, ms), nil
|
||||||
|
} else if newLine == -1 {
|
||||||
|
return fmt.Sprintf("[%02d:%02d.%02d]", m, s, ms), nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("<%02d:%02d.%02d>", m, s, ms), nil
|
return fmt.Sprintf("<%02d:%02d.%02d>", m, s, ms), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
divs := parsedTTML.FindElement("tt").FindElement("body").FindElements("div")
|
divs := parsedTTML.FindElement("tt").FindElement("body").FindElements("div")
|
||||||
//get trans
|
|
||||||
if len(parsedTTML.FindElement("tt").FindElements("head")) > 0 {
|
|
||||||
if len(parsedTTML.FindElement("tt").FindElement("head").FindElements("metadata")) > 0 {
|
|
||||||
Metadata := parsedTTML.FindElement("tt").FindElement("head").FindElement("metadata")
|
|
||||||
if len(Metadata.FindElements("iTunesMetadata")) > 0 {
|
|
||||||
iTunesMetadata := Metadata.FindElement("iTunesMetadata")
|
|
||||||
if len(iTunesMetadata.FindElements("translations")) > 0 {
|
|
||||||
if len(iTunesMetadata.FindElement("translations").FindElements("translation")) > 0 {
|
|
||||||
divs = iTunesMetadata.FindElement("translations").FindElements("translation")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, div := range divs {
|
for _, div := range divs {
|
||||||
for _, item := range div.ChildElements() {
|
for _, item := range div.ChildElements() { //LINES
|
||||||
var lrcSyllables []string
|
var lrcSyllables []string
|
||||||
var i int = 0
|
var i int = 0
|
||||||
var endTime string
|
var endTime, transLine string
|
||||||
for _, lyrics := range item.Child {
|
for _, lyrics := range item.Child { //WORDS
|
||||||
if _, ok := lyrics.(*etree.CharData); ok {
|
if _, ok := lyrics.(*etree.CharData); ok { //是否为span之间的空格
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
lrcSyllables = append(lrcSyllables, " ")
|
lrcSyllables = append(lrcSyllables, " ")
|
||||||
continue
|
continue
|
||||||
@@ -220,11 +212,12 @@ func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
|||||||
if lyric.SelectAttr("begin") == nil {
|
if lyric.SelectAttr("begin") == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
beginTime, err := parseTime(lyric.SelectAttr("begin").Value, i == 0)
|
beginTime, err := parseTime(lyric.SelectAttr("begin").Value, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
endTime, err = parseTime(lyric.SelectAttr("end").Value, false)
|
|
||||||
|
endTime, err = parseTime(lyric.SelectAttr("end").Value, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -243,6 +236,39 @@ func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
|||||||
text = lyric.SelectAttr("text").Value
|
text = lyric.SelectAttr("text").Value
|
||||||
}
|
}
|
||||||
lrcSyllables = append(lrcSyllables, fmt.Sprintf("%s%s", beginTime, text))
|
lrcSyllables = append(lrcSyllables, fmt.Sprintf("%s%s", beginTime, text))
|
||||||
|
if i == 0 {
|
||||||
|
transBeginTime, _ := parseTime(lyric.SelectAttr("begin").Value, -1)
|
||||||
|
if len(parsedTTML.FindElement("tt").FindElements("head")) > 0 {
|
||||||
|
if len(parsedTTML.FindElement("tt").FindElement("head").FindElements("metadata")) > 0 {
|
||||||
|
Metadata := parsedTTML.FindElement("tt").FindElement("head").FindElement("metadata")
|
||||||
|
if len(Metadata.FindElements("iTunesMetadata")) > 0 {
|
||||||
|
iTunesMetadata := Metadata.FindElement("iTunesMetadata")
|
||||||
|
if len(iTunesMetadata.FindElements("translations")) > 0 {
|
||||||
|
if len(iTunesMetadata.FindElement("translations").FindElements("translation")) > 0 {
|
||||||
|
xpath := fmt.Sprintf("//text[@for='%s']", item.SelectAttr("itunes:key").Value)
|
||||||
|
trans := iTunesMetadata.FindElement("translations").FindElement("translation").FindElement(xpath)
|
||||||
|
var transTxt string
|
||||||
|
if trans.SelectAttr("text") == nil {
|
||||||
|
var textTmp []string
|
||||||
|
for _, span := range trans.Child {
|
||||||
|
if _, ok := span.(*etree.CharData); ok {
|
||||||
|
textTmp = append(textTmp, span.(*etree.CharData).Data)
|
||||||
|
} else {
|
||||||
|
textTmp = append(textTmp, span.(*etree.Element).Text())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transTxt = strings.Join(textTmp, "")
|
||||||
|
} else {
|
||||||
|
transTxt = lyric.SelectAttr("text").Value
|
||||||
|
}
|
||||||
|
//fmt.Println(transTxt)
|
||||||
|
transLine = transBeginTime + transTxt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
//endTime, err := parseTime(item.SelectAttr("end").Value)
|
//endTime, err := parseTime(item.SelectAttr("end").Value)
|
||||||
@@ -250,6 +276,9 @@ func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
|||||||
// return "", err
|
// return "", err
|
||||||
//}
|
//}
|
||||||
lrcLines = append(lrcLines, strings.Join(lrcSyllables, "")+endTime)
|
lrcLines = append(lrcLines, strings.Join(lrcSyllables, "")+endTime)
|
||||||
|
if len(transLine) > 0 {
|
||||||
|
lrcLines = append(lrcLines, transLine)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(lrcLines, "\n"), nil
|
return strings.Join(lrcLines, "\n"), nil
|
||||||
|
|||||||
Reference in New Issue
Block a user