mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-09 14:18:11 +02:00
feat: add lyrics source tracking, Paxsenix partner, and dedicated lyrics provider settings page
- Add getLyricsLRCWithSource to return lyrics with source metadata - Display lyrics source in track metadata screen - Improve LRC parsing to preserve background vocal tags - Add dedicated LyricsProviderPriorityPage for provider configuration - Add Paxsenix as lyrics proxy partner for Apple Music/QQ Music - Handle inline timestamps and speaker prefixes in LRC display
This commit is contained in:
@@ -1008,6 +1008,64 @@ func GetLyricsLRC(spotifyID, trackName, artistName string, filePath string, dura
|
||||
return lrcContent, nil
|
||||
}
|
||||
|
||||
func GetLyricsLRCWithSource(spotifyID, trackName, artistName string, filePath string, durationMs int64) (string, error) {
|
||||
if filePath != "" {
|
||||
lyrics, err := ExtractLyrics(filePath)
|
||||
if err == nil && lyrics != "" {
|
||||
result := map[string]interface{}{
|
||||
"lyrics": lyrics,
|
||||
"source": "Embedded",
|
||||
"sync_type": "EMBEDDED",
|
||||
"instrumental": false,
|
||||
}
|
||||
jsonBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
result := map[string]interface{}{
|
||||
"lyrics": "",
|
||||
"source": "",
|
||||
"sync_type": "",
|
||||
"instrumental": false,
|
||||
}
|
||||
jsonBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
client := NewLyricsClient()
|
||||
durationSec := float64(durationMs) / 1000.0
|
||||
lyricsData, err := client.FetchLyricsAllSources(spotifyID, trackName, artistName, durationSec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lrcContent := ""
|
||||
if lyricsData.Instrumental {
|
||||
lrcContent = "[instrumental:true]"
|
||||
} else {
|
||||
lrcContent = convertToLRCWithMetadata(lyricsData, trackName, artistName)
|
||||
}
|
||||
|
||||
result := map[string]interface{}{
|
||||
"lyrics": lrcContent,
|
||||
"source": lyricsData.Source,
|
||||
"sync_type": lyricsData.SyncType,
|
||||
"instrumental": lyricsData.Instrumental,
|
||||
}
|
||||
jsonBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
func EmbedLyricsToFile(filePath, lyrics string) (string, error) {
|
||||
err := EmbedLyrics(filePath, lyrics)
|
||||
if err != nil {
|
||||
|
||||
@@ -608,6 +608,13 @@ func parseSyncedLyrics(syncedLyrics string) []LyricsLine {
|
||||
continue
|
||||
}
|
||||
|
||||
// Preserve Apple/QQ background vocal tags by attaching them to
|
||||
// the previous timed line. This keeps [bg:...] in final exported LRC.
|
||||
if strings.HasPrefix(line, "[bg:") && len(lines) > 0 {
|
||||
lines[len(lines)-1].Words = strings.TrimSpace(lines[len(lines)-1].Words + "\n" + line)
|
||||
continue
|
||||
}
|
||||
|
||||
matches := lrcPattern.FindStringSubmatch(line)
|
||||
if len(matches) == 5 {
|
||||
startMs := lrcTimestampToMs(matches[1], matches[2], matches[3])
|
||||
|
||||
@@ -289,7 +289,7 @@ func formatPaxContent(lyricsType string, content []paxLyrics, multiPersonWordByW
|
||||
|
||||
timestamp := msToLRCTimestamp(int64(line.Timestamp))
|
||||
|
||||
if lyricsType == "Syllable" {
|
||||
if strings.EqualFold(lyricsType, "Syllable") {
|
||||
sb.WriteString(timestamp)
|
||||
if multiPersonWordByWord {
|
||||
if line.OppositeTurn {
|
||||
|
||||
Reference in New Issue
Block a user