I’m working on a Python script to update music file metadata with proper album names and cover art using the MusicBrainz API. The script is supposed to fetch the album name based on the artist and title of the song, but it often returns random albums such as compilation or collection albums or just empty instead of the correct album where the song originally appeared.
Here is the relevant part of my code:
import os
import mutagen
import musicbrainzngs
import requests
import certifi
from mutagen.id3 import ID3, TALB, TPE1, TIT2, APIC, error
# Configure MusicBrainz
musicbrainzngs.set_useragent("Album Finder", "0.1", "[email protected]")
def get_album_info(artist, title):
try:
result = musicbrainzngs.search_recordings(artist=artist, recording=title, limit=5, strict=True)
for recording in result['recording-list']:
for release in recording['release-list']:
if 'secondary-type-list' in release and 'Compilation' in release['secondary-type-list']:
continue # Skip compilations
if release['status'] == 'Official' and 'Album' in release['release-group']['primary-type']:
album_title = release['title']
album_id = release['id']
print(f"Found album: {album_title} with ID: {album_id} for artist: {artist} and title: {title}")
return album_title, album_id
# If no suitable album is found
print(f"No suitable album found for artist: {artist} and title: {title}. Setting album to 'Single'.")
return "Single", None
except (IndexError, KeyError):
print(f"No album found for artist: {artist} and title: {title}. Setting album to 'Single'.")
return "Single", None
def get_cover_art(album_id):
if not album_id:
return None
try:
cover_art_list = musicbrainzngs.get_image_list(album_id)
if 'images' in cover_art_list and cover_art_list['images']:
cover_art_url = cover_art_list['images'][0]['image']
cover_art_data = requests.get(cover_art_url, verify=certifi.where()).content
print(f"Found cover art for album ID: {album_id}")
return cover_art_data
else:
print(f"No cover art found for album ID: {album_id}")
return None
except musicbrainzngs.ResponseError as e:
print(f"Error retrieving cover art for album ID: {album_id} - {e}")
return None
def update_file_metadata(file_path):
print(f"Processing file: {file_path}")
try:
audio = ID3(file_path)
except error.ID3NoHeaderError:
print(f"No ID3 header found for file: {file_path}. Skipping.")
return
artist_frame = audio.get('TPE1', None)
title_frame = audio.get('TIT2', None)
if not artist_frame or not title_frame:
print("Artist or title tag not found. Skipping file.")
return
artist = artist_frame.text[0] if artist_frame and isinstance(artist_frame, mutagen.id3.TextFrame) else None
title = title_frame.text[0] if title_frame and isinstance(title_frame, mutagen.id3.TextFrame) else None
if not artist or not title:
print("Artist or title tag not correctly formatted. Skipping file.")
return
print(f"Artist: {artist}, Title: {title}")
album_title, album_id = get_album_info(artist, title)
# Update album title and cover art
audio.delall('TALB')
audio.add(TALB(encoding=3, text=album_title))
cover_art_data = get_cover_art(album_id)
if cover_art_data:
audio.delall('APIC')
audio.add(APIC(
encoding=3,
mime='image/jpeg',
type=3, desc='Cover',
data=cover_art_data
))
audio.save(file_path)
print(f"Updated file: {file_path} with album: {album_title}")
def process_folder(folder_path):
for root, _, files in os.walk(folder_path):
for file in files:
if file.endswith(('.mp3', '.flac', '.ogg', '.m4a')):
file_path = os.path.join(root, file)
update_file_metadata(file_path)
if __name__ == "__main__":
folder_path = "/Users/user/Documents/MUSIC/11"
process_folder(folder_path)
I was testing with the song “Betty Davis Eyes” by Kim Carnes, and the script sometimes returns compilation albums instead of the correct album or it couldn’t find anything:
Processing file: /Users/user/Documents/MUSIC/11/O.N.A. - KoÅa czasu.mp3
Artist or title tag not found. Skipping file.
Processing file: /Users/user/Documents/MUSIC/11/Kim Carnes - Bett Davis Eyes.mp3
Artist: Kim Carnes, Title: Bette Davis Eyes
Found album: Old Hits of 80’s, Volume 2 with ID: a477e219-f84f-4296-9688-b7629eea5e93 for artist: Kim Carnes and title: Bette Davis Eyes
Found cover art for album ID: a477e219-f84f-4296-9688-b7629eea5e93
Updated file: /Users/user/Documents/MUSIC/11/Kim Carnes - Bett Davis Eyes.mp3 with album: Old Hits of 80’s, Volume 2
Processing file: /Users/user/Documents/MUSIC/11/02 Oblivion.mp3
Artist: Royal Blood, Title: Oblivion
Found album: Typhoons with ID: 62375d86-9cd2-4866-8274-ad738730b1e0 for artist: Royal Blood and title: Oblivion
Found cover art for album ID: 62375d86-9cd2-4866-8274-ad738730b1e0
Updated file: /Users/user/Documents/MUSIC/11/02 Oblivion.mp3 with album: Typhoons
How can I modify my script to ensure it fetches the original album where the song first appeared, rather than compilations or other types of releases?