mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
fix album-level tag consistency for mixed-artist tracks
Use album artist overrides during album ripping so compilation-style tracks do not change album performer tags, and add safer disc-number fallbacks for metadata/path generation when providers omit disc fields.
This commit is contained in:
@@ -39,6 +39,7 @@ type Main struct {
|
||||
type ripTrackOptions struct {
|
||||
albumFolder string
|
||||
albumEmbedCover string
|
||||
albumArtist string
|
||||
index int
|
||||
total int
|
||||
albumDiscTotal int
|
||||
@@ -498,7 +499,7 @@ func (m *Main) ripAlbum(ctx context.Context, p provider.Client, source, albumID
|
||||
|
||||
if !m.Config.Session.Downloads.Concurrency || m.Config.Session.Downloads.MaxConnections == 1 {
|
||||
for i, trackID := range trackIDs {
|
||||
opts := ripTrackOptions{albumFolder: folder, albumEmbedCover: artRes.EmbedPath, index: i + 1, total: total, albumDiscTotal: discTotal}
|
||||
opts := ripTrackOptions{albumFolder: folder, albumEmbedCover: artRes.EmbedPath, albumArtist: albumArtist, index: i + 1, total: total, albumDiscTotal: discTotal}
|
||||
if err := m.ripTrack(ctx, p, source, trackID, "", opts); err != nil {
|
||||
failures++
|
||||
m.logf("track failed: id=%s reason=%v\n", trackID, err)
|
||||
@@ -523,7 +524,7 @@ func (m *Main) ripAlbum(ctx context.Context, p provider.Client, source, albumID
|
||||
go func(idx int, tid string) {
|
||||
defer wg.Done()
|
||||
defer func() { <-sem }()
|
||||
opts := ripTrackOptions{albumFolder: folder, albumEmbedCover: artRes.EmbedPath, index: idx, total: total, albumDiscTotal: discTotal}
|
||||
opts := ripTrackOptions{albumFolder: folder, albumEmbedCover: artRes.EmbedPath, albumArtist: albumArtist, index: idx, total: total, albumDiscTotal: discTotal}
|
||||
if err := m.ripTrack(ctx, p, source, tid, "", opts); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
@@ -836,6 +837,15 @@ func (m *Main) trackOutputPath(source, id, title, ext string, trackMeta map[stri
|
||||
base = albumFolder
|
||||
if m.Config.Session.Downloads.DiscSubdirectories && albumDiscTotal > 1 {
|
||||
discNumber := intFromAny(trackMeta["media_number"])
|
||||
if discNumber == 0 {
|
||||
discNumber = intFromAny(trackMeta["volumeNumber"])
|
||||
}
|
||||
if discNumber == 0 {
|
||||
discNumber = intFromAny(trackMeta["disk_number"])
|
||||
}
|
||||
if discNumber == 0 {
|
||||
discNumber = 1
|
||||
}
|
||||
if discNumber > 0 {
|
||||
base = filepath.Join(base, "Disc "+strconv.Itoa(discNumber))
|
||||
}
|
||||
@@ -1012,6 +1022,9 @@ func buildTagMetadata(trackMeta map[string]any, title, source, trackID string, o
|
||||
if albumArtist == "" {
|
||||
albumArtist = artist
|
||||
}
|
||||
if strings.TrimSpace(opts.albumArtist) != "" {
|
||||
albumArtist = strings.TrimSpace(opts.albumArtist)
|
||||
}
|
||||
trackNumber := intFromAny(trackMeta["track_number"])
|
||||
if trackNumber == 0 {
|
||||
trackNumber = intFromAny(trackMeta["trackNumber"])
|
||||
@@ -1020,6 +1033,9 @@ func buildTagMetadata(trackMeta map[string]any, title, source, trackID string, o
|
||||
if discNumber == 0 {
|
||||
discNumber = intFromAny(trackMeta["volumeNumber"])
|
||||
}
|
||||
if discNumber == 0 {
|
||||
discNumber = intFromAny(trackMeta["disk_number"])
|
||||
}
|
||||
date := stringFromAny(trackMeta["release_date_original"])
|
||||
if date == "" {
|
||||
date = stringFromAny(trackMeta["release_date"])
|
||||
@@ -1046,9 +1062,15 @@ func buildTagMetadata(trackMeta map[string]any, title, source, trackID string, o
|
||||
if discTotal == 0 {
|
||||
discTotal = intFromAny(trackMeta["numberOfVolumes"])
|
||||
}
|
||||
if discTotal == 0 && opts.albumDiscTotal > 0 {
|
||||
discTotal = opts.albumDiscTotal
|
||||
}
|
||||
if opts.forPlaylist {
|
||||
discTotal = 1
|
||||
}
|
||||
if !opts.forPlaylist && discNumber == 0 {
|
||||
discNumber = 1
|
||||
}
|
||||
|
||||
genre := nestedString(trackMeta, "genre", "name")
|
||||
if genre == "" {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"streamrip-go/internal/audio/tag"
|
||||
@@ -368,6 +369,51 @@ func TestResolveAllFailedReturnsError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTagMetadataUsesAlbumArtistOverride(t *testing.T) {
|
||||
meta := map[string]any{
|
||||
"title": "One Step Too Far",
|
||||
"track_number": float64(15),
|
||||
"performer": map[string]any{"name": "Faithless"},
|
||||
"artist": map[string]any{"name": "Faithless"},
|
||||
"album": map[string]any{
|
||||
"id": "23324600",
|
||||
"title": "Greatest Hits (Deluxe)",
|
||||
"artist": map[string]any{"name": "Faithless"},
|
||||
},
|
||||
}
|
||||
tags := buildTagMetadata(meta, "One Step Too Far", "tidal", "23324615", ripTrackOptions{albumArtist: "Dido", albumDiscTotal: 2})
|
||||
if tags.AlbumArtist != "Dido" {
|
||||
t.Fatalf("album artist = %q, want Dido", tags.AlbumArtist)
|
||||
}
|
||||
if tags.DiscNumber != 1 {
|
||||
t.Fatalf("disc number = %d, want 1", tags.DiscNumber)
|
||||
}
|
||||
if tags.DiscTotal != 2 {
|
||||
t.Fatalf("disc total = %d, want 2", tags.DiscTotal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrackOutputPathFallsBackToDisc1(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
d := config.DefaultConfigData()
|
||||
d.Downloads.Folder = tmp
|
||||
d.Downloads.DiscSubdirectories = true
|
||||
d.Downloads.SourceSubdirectories = false
|
||||
cfg := &config.Config{File: d, Session: d}
|
||||
m := &Main{Config: cfg}
|
||||
|
||||
meta := map[string]any{
|
||||
"title": "Song",
|
||||
"track_number": float64(1),
|
||||
"performer": map[string]any{"name": "Dido"},
|
||||
"album": map[string]any{"id": "a", "title": "Greatest Hits", "artist": map[string]any{"name": "Dido"}},
|
||||
}
|
||||
path := m.trackOutputPath("tidal", "1", "Song", "flac", meta, filepath.Join(tmp, "Album"), 2)
|
||||
if !strings.Contains(path, string(filepath.Separator)+"Disc 1"+string(filepath.Separator)) {
|
||||
t.Fatalf("expected Disc 1 subdir in path, got %q", path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaylistRipPipeline(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user