Repository: yt-dlp/yt-dlp

Issue:
[bandcamp.com] add album_artist metadata field for tracks
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I remove or skip any mandatory\* field

### Checklist

- [X] I'm requesting a site-specific feature
- [X] I've verified that I'm running yt-dlp version **2022.11.11** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

USA and EU at least, pretty much global I believe.

### Example URLs

Any album with tracks of differing artists, for example:
https://damnably.bandcamp.com/album/damnably-famnably-14th-birthday-free-compilation
https://isolatedsw.bandcamp.com/album/isolated-free-compilation-vol-1
https://diskotopia.bandcamp.com/album/dsk-f-w-2016-2017-free-compilation

### Provide a description that is worded well enough to be understood

Bandcamp tracks currently do not include the `album_artist` metadata field which makes downloading compilations difficult specifically when the user desires the downloaded album to be grouped together in a directory under a single artist name, a common pattern for media servers like [Jellyfin](https://jellyfin.org/):
```
.
└── artist name
    └── album name
        ├── 1 foo.mp3
        ├── 2 bar.mp3
        └── 3 baz.mp3
```
For albums containing tracks where all the artists are identical, this can be done easily with `--format %(artist)s/%(album)s/%(track_number)s %(track)s.%(ext)s`. But for compilation albums (albums with tracks of differing artists), the album will be separated into many `artist name /album name` directories which breaks apart the album and is not good for Jellyfin and other media servers because they will see it as multiple albums with the same name.

What I'm proposing is that the bandcamp extractor include an `album_artist` field so a user can use the above directory layout scheme even with compilation albums by using `--format %(album_artist)s/%(album)s/%(track_number)s %(track)s.%(ext)s`. Bandcamp already associates a single artist which owns each album, but that artist information isn't provided in each track's JSON metadata so it needs to be scraped from the HTML of the track webpage:

![2022-11-14-10:10:15-screenshot](https://user-images.githubusercontent.com/22163194/201735621-8bf7b983-67e2-4d30-a298-679dea7da916.png)


### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['-vU', '--output', 'ignore/%(artist)s/%(track_number)s %(track)s.%(ext)s', 'https://damnably.bandcamp.com/album/damnably-famnably-14th-birthday-free-compilation']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.11.11 [8b644025b] (source)
[debug] Lazy loading extractors is disabled
[debug] Plugins: ['SamplePluginIE', 'SamplePluginPP']
[debug] Git HEAD: d7b460d0e
[debug] Python 3.10.7 (CPython x86_64 64bit) - Linux-5.19.16-200.fc36.x86_64-x86_64-with-glibc2.35 (OpenSSL 3.0.5 5 Jul 2022, glibc 2.35)
[debug] exe versions: ffmpeg 5.0.1 (setts), ffprobe 5.0.1
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2021.10.08, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.1
[debug] Proxy map: {}
[debug] Loaded 1725 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.11.11, Current version: 2022.11.11
yt-dlp is up to date (2022.11.11)
[debug] [Bandcamp:album] Extracting URL: https://damnably.bandcamp.com/album/damnably-famnably-14th-birthday-free-compilation
[Bandcamp:album] damnably-famnably-14th-birthday-free-compilation: Downloading webpage
[download] Downloading playlist: Damnably Famnably 14th Birthday FREE Compilation
[Bandcamp:album] Playlist Damnably Famnably 14th Birthday FREE Compilation: Downloading 22 items of 22
[download] Downloading item 1 of 22
[debug] [Bandcamp] Extracting URL: https://damnably.bandcamp.com/track/old-town
[Bandcamp] old-town: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 3426938226: Downloading 1 format(s): mp3-128
[debug] Invoking http downloader on "https://t4.bcbits.com/stream/ad55924dcf5d5c30270a0643d30887ee/mp3-128/3426938226?p=0&ts=1668536489&t=8dca28d1becd6b438721c91c639a6f3f8020b3c8&token=1668536489_76a7045038a78721586c55213e322ff8175eb24d"
[download] Destination: ignore/Say Sue Me/1 Say Sue Me - Old Town.mp3
[download] 100% of    3.56MiB in 00:00:01 at 3.53MiB/s
[download] Downloading item 2 of 22
[debug] [Bandcamp] Extracting URL: https://damnably.bandcamp.com/track/dont-light-my-fire
[Bandcamp] dont-light-my-fire: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 2553803020: Downloading 1 format(s): mp3-128
[debug] Invoking http downloader on "https://t4.bcbits.com/stream/0ac3265b9ff5685ed77df0c806a43b61/mp3-128/2553803020?p=0&ts=1668536491&t=8b2551f375287c9f9e8089a7bfb1532ce731fd73&token=1668536491_26025717c9fadcce2250a1e533101465e1c3e133"
[download] Destination: ignore/Otoboke Beaver/2 Otoboke Beaver - Don't Light My Fire.mp3
[download] 100% of    2.09MiB in 00:00:00 at 3.93MiB/s
[download] Downloading item 3 of 22
[debug] [Bandcamp] Extracting URL: https://damnably.bandcamp.com/track/national-police-shit-2
[Bandcamp] national-police-shit-2: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 1007927037: Downloading 1 format(s): mp3-128
[debug] Invoking http downloader on "https://t4.bcbits.com/stream/0a7e36da45aa922ca52cfe8cb12961f3/mp3-128/1007927037?p=0&ts=1668536493&t=98fc6dc7960528ffad423abe9762bb9e25cd024f&token=1668536493_634902abb1ca63aaf18e6b5e2258eb4f3b82cbb0"
[download] Destination: ignore/Drinking Boys and Girls Choir/3 Drinking Boys and Girls Choir - National Police Shit.mp3
[download] 100% of    1.42MiB in 00:00:01 at 957.48KiB/s
[download] Downloading item 4 of 22
[debug] [Bandcamp] Extracting URL: https://damnably.bandcamp.com/track/dream-grrrl-single-version-2
[Bandcamp] dream-grrrl-single-version-2: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 3278203047: Downloading 1 format(s): mp3-128
[debug] Invoking http downloader on "https://t4.bcbits.com/stream/43a05c30dcaaad31dfaf57e92a104a2f/mp3-128/3278203047?p=0&ts=1668536495&t=0b3ecc6fb85bc6a8db4708fdeda28265e6a262c6&token=1668536495_7ff6d10331e95f09bcebdde48c86ed377a3669d3"
[download] Destination: ignore/Grrrl Gang/4 Grrrl Gang - Dream Grrrl (Single Version).mp3
[download] 100% of    3.14MiB in 00:00:01 at 2.11MiB/s
[download] Downloading item 5 of 22
[debug] [Bandcamp] Extracting URL: https://damnably.bandcamp.com/track/teenage-wasteland
[Bandcamp] teenage-wasteland: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 2875477778: Downloading 1 format(s): mp3-128
[debug] Invoking http downloader on "https://t4.bcbits.com/stream/feff7121725401cac13cb5a8b752259d/mp3-128/2875477778?p=0&ts=1668536497&t=fcf2708340d75aaa2694b8c5d22a722783592f62&token=1668536497_2a2a8b07fe0e2ec81e6ff120b55ca385c830bbac"
[download] Destination: ignore/Wussy/5 Wussy - Teenage Wasteland.mp3
[download] 100% of    4.27MiB in 00:00:00 at 4.60MiB/s
```



Discussion:

Resolving patch:
diff --git a/yt_dlp/extractor/bandcamp.py b/yt_dlp/extractor/bandcamp.py
--- a/yt_dlp/extractor/bandcamp.py
+++ b/yt_dlp/extractor/bandcamp.py
@@ -29,11 +29,18 @@ class BandcampIE(InfoExtractor):
         'info_dict': {
             'id': '1812978515',
             'ext': 'mp3',
-            'title': "youtube-dl  \"'/\\ä↭ - youtube-dl  \"'/\\ä↭ - youtube-dl test song \"'/\\ä↭",
+            'title': 'youtube-dl "\'/\\ä↭ - youtube-dl "\'/\\ä↭ - youtube-dl test song "\'/\\ä↭',
             'duration': 9.8485,
-            'uploader': 'youtube-dl  "\'/\\ä↭',
+            'uploader': 'youtube-dl "\'/\\ä↭',
             'upload_date': '20121129',
             'timestamp': 1354224127,
+            'track': 'youtube-dl "\'/\\ä↭ - youtube-dl test song "\'/\\ä↭',
+            'album_artist': 'youtube-dl "\'/\\ä↭',
+            'track_id': '1812978515',
+            'artist': 'youtube-dl "\'/\\ä↭',
+            'uploader_url': 'https://youtube-dl.bandcamp.com',
+            'uploader_id': 'youtube-dl',
+            'thumbnail': 'https://f4.bcbits.com/img/a3216802731_5.jpg',
         },
         '_skip': 'There is a limit of 200 free downloads / month for the test song'
     }, {
@@ -41,7 +48,8 @@ class BandcampIE(InfoExtractor):
         'url': 'http://benprunty.bandcamp.com/track/lanius-battle',
         'info_dict': {
             'id': '2650410135',
-            'ext': 'aiff',
+            'ext': 'm4a',
+            'acodec': r're:[fa]lac',
             'title': 'Ben Prunty - Lanius (Battle)',
             'thumbnail': r're:^https?://.*\.jpg$',
             'uploader': 'Ben Prunty',
@@ -54,7 +62,10 @@ class BandcampIE(InfoExtractor):
             'track_number': 1,
             'track_id': '2650410135',
             'artist': 'Ben Prunty',
+            'album_artist': 'Ben Prunty',
             'album': 'FTL: Advanced Edition Soundtrack',
+            'uploader_url': 'https://benprunty.bandcamp.com',
+            'uploader_id': 'benprunty',
         },
     }, {
         # no free download, mp3 128
@@ -75,7 +86,34 @@ class BandcampIE(InfoExtractor):
             'track_number': 5,
             'track_id': '2584466013',
             'artist': 'Mastodon',
+            'album_artist': 'Mastodon',
             'album': 'Call of the Mastodon',
+            'uploader_url': 'https://relapsealumni.bandcamp.com',
+            'uploader_id': 'relapsealumni',
+        },
+    }, {
+        # track from compilation album (artist/album_artist difference)
+        'url': 'https://diskotopia.bandcamp.com/track/safehouse',
+        'md5': '19c5337bca1428afa54129f86a2f6a69',
+        'info_dict': {
+            'id': '1978174799',
+            'ext': 'mp3',
+            'title': 'submerse - submerse - Safehouse',
+            'thumbnail': r're:^https?://.*\.jpg$',
+            'uploader': 'submerse',
+            'timestamp': 1480779297,
+            'upload_date': '20161203',
+            'release_timestamp': 1481068800,
+            'release_date': '20161207',
+            'duration': 154.066,
+            'track': 'submerse - Safehouse',
+            'track_number': 3,
+            'track_id': '1978174799',
+            'artist': 'submerse',
+            'album_artist': 'Diskotopia',
+            'album': 'DSK F/W 2016-2017 Free Compilation',
+            'uploader_url': 'https://diskotopia.bandcamp.com',
+            'uploader_id': 'diskotopia',
         },
     }]
 
@@ -121,6 +159,9 @@ def _real_extract(self, url):
         embed = self._extract_data_attr(webpage, title, 'embed', False)
         current = tralbum.get('current') or {}
         artist = embed.get('artist') or current.get('artist') or tralbum.get('artist')
+        album_artist = self._html_search_regex(
+            r'<h3 class="albumTitle">[\S\s]*?by\s*<span>\s*<a href="[^>]+">\s*([^>]+?)\s*</a>',
+            webpage, 'album artist', fatal=False)
         timestamp = unified_timestamp(
             current.get('publish_date') or tralbum.get('album_publish_date'))
 
@@ -205,6 +246,7 @@ def _real_extract(self, url):
             'track_id': track_id,
             'artist': artist,
             'album': embed.get('album_title'),
+            'album_artist': album_artist,
             'formats': formats,
         }
 


Test patch: