Repository: beetbox/beets

Issue:
Use Artist Credits for tag data, but "actual" artist data for filenaming
Currently beets will always normalise [artist credit](https://musicbrainz.org/doc/Artist_Credit) data to the current artist name. However, I want to see when playing the music when, e.g., [Orgi-E](https://musicbrainz.org/artist/345fe3da-b2cb-4ad4-a1a5-43afc903663d) was credited as [Klamfyr](https://musicbrainz.org/release/d09b3568-e9cc-4458-bcf7-0c215cca75ce), but I still like the normalisation for file tree organisation purposes. This should probably be an option though, as other people will likely want to always normalise the name (and others might want to not normalise the name in the path as well).

(Somewhat related morituri issues: thomasvs/morituri#80, thomasvs/morituri#48)



Discussion:
We do collect `artist_credit` and `albumartist_credit` fields (separate from `artist` and `albumartist`). Is anything missing about that piece of functionality? (That is, you can use `$albumartist_credit` in your path formats.)

But I don't want to use it in the path - I want to have it in the file's metadata. That's the point. :)

Ah! Sorry for being slow. So if I understand correctly, this would work like `original_year`, in that the purpose is interoperability with other software. So the credit would go in the `$artist` field, and the "true" artist name would probably go in a separate flexible attribute like `$artist_canonical` in case you want to put it in a path.

This would be a great feature. Currently I have some tracks that have the artist `[unknown]` but have a more interesting credited name. Currently they just get tagged as `[unknown]`.

It's obviously useful to tag with the canonical artist name, as that makes it possible to group tracks by artist and search, but with artist names like `[unknown]` there's no real downside to just using the canonical name.

+1

Out of my 4029 albums only 97 have differing albumartist and albumartist_credit values (~2.4%). I checked about a dozen of these albums manually against Discogs, iTunes, Amazon and Google Play. All sites use the artist credit over beets' "canonical" version.

A few examples:

- ["Margaret Antwood - Virtuous.scr"](https://musicbrainz.org/release/fbfd2d50-ece4-4595-8714-47116e25ba12) on MusicBrainz but "Antwood" on [Discogs](https://www.discogs.com/Antwood-Virtuousscr/master/1002193) and [iTunes](https://itunes.apple.com/us/album/virtuous-scr/id1085156191)

- ["MF DOOM - Born Like This"](https://musicbrainz.org/release-group/c748987e-7cb5-3880-b246-d20af2b136f3) on MusicBrainz but just "DOOM" on [Discogs](https://www.discogs.com/DOOM-Born-Like-This/master/51121) and [iTunes](https://itunes.apple.com/gb/album/born-like-this-bonus-version/id808196856)

- ["Wu‐Tang Clan - The Saga Continues"](https://musicbrainz.org/release/671b82b9-0b27-4322-b172-c8b721d9427a) but just "Wu Tang" on [Discogs](https://www.discogs.com/Wu-Tang-The-Saga-Continues/master/1252289) and [iTunes](https://itunes.apple.com/us/album/the-saga-continues/id1285602476)

It seems like MusicBrainz treats the artist field as the artist's _current_ name, which can change and cause large, unexpected metadata changes to existing files (e.g. when Jay-Z was renamed to "JAY-Z" on MusicBrainz).

Given the above, it might make sense to prefer artist credit as the default for future imports (although I don't mind one way or the other if it's at least user-configurable).
+1 on this.

I reported it earlier (as #2854) because my GitHub issue search skills were lacking at the time.

@sampsyo What can we do to make progress on this feature? How do you think it could/should be implemented?
It seems like adding a config option is the right thing! As I said above, a motivated implementor could model it after the way the `original_year` option currently works.

Resolving patch:
diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py
--- a/beets/autotag/__init__.py
+++ b/beets/autotag/__init__.py
@@ -63,12 +63,19 @@ def apply_metadata(album_info, mapping):
     mapping from Items to TrackInfo objects.
     """
     for item, track_info in mapping.items():
-        # Album, artist, track count.
-        if track_info.artist:
-            item.artist = track_info.artist
+        # Artist or artist credit.
+        if config['artist_credit']:
+            item.artist = (track_info.artist_credit or
+                           track_info.artist or
+                           album_info.artist_credit or
+                           album_info.artist)
+            item.albumartist = (album_info.artist_credit or
+                                album_info.artist)
         else:
-            item.artist = album_info.artist
-        item.albumartist = album_info.artist
+            item.artist = (track_info.artist or album_info.artist)
+            item.albumartist = album_info.artist
+
+        # Album.
         item.album = album_info.album
 
         # Artist sort and credit names.


Test patch:
diff --git a/test/test_autotag.py b/test/test_autotag.py
--- a/test/test_autotag.py
+++ b/test/test_autotag.py
@@ -616,12 +616,13 @@ def info(index, title, length):
 
 
 class ApplyTestUtil(object):
-    def _apply(self, info=None, per_disc_numbering=False):
+    def _apply(self, info=None, per_disc_numbering=False, artist_credit=False):
         info = info or self.info
         mapping = {}
         for i, t in zip(self.items, info.tracks):
             mapping[i] = t
         config['per_disc_numbering'] = per_disc_numbering
+        config['artist_credit'] = artist_credit
         autotag.apply_metadata(info, mapping)
 
 
@@ -706,6 +707,24 @@ def test_per_disc_numbering_track_total(self):
         self.assertEqual(self.items[0].tracktotal, 1)
         self.assertEqual(self.items[1].tracktotal, 1)
 
+    def test_artist_credit(self):
+        self._apply(artist_credit=True)
+        self.assertEqual(self.items[0].artist, 'trackArtistCredit')
+        self.assertEqual(self.items[1].artist, 'albumArtistCredit')
+        self.assertEqual(self.items[0].albumartist, 'albumArtistCredit')
+        self.assertEqual(self.items[1].albumartist, 'albumArtistCredit')
+
+    def test_artist_credit_prefers_artist_over_albumartist_credit(self):
+        self.info.tracks[0].artist = 'oldArtist'
+        self.info.tracks[0].artist_credit = None
+        self._apply(artist_credit=True)
+        self.assertEqual(self.items[0].artist, 'oldArtist')
+
+    def test_artist_credit_falls_back_to_albumartist(self):
+        self.info.artist_credit = None
+        self._apply(artist_credit=True)
+        self.assertEqual(self.items[1].artist, 'artistNew')
+
     def test_mb_trackid_applied(self):
         self._apply()
         self.assertEqual(self.items[0].mb_trackid,