def getCoverArt(self, path, release_id): """ Get cover art image from Cover Art Archive. :param path: where to store the fetched image :type path: str :param release_id: a release id (self.program.metadata.mbid) :type release_id: str :returns: path to the downloaded cover art, else `None` :rtype: str or None """ cover_art_path = os.path.join(path, 'cover.jpg') logger.debug('fetching cover art for release: %r', release_id) try: data = musicbrainzngs.get_image_front(release_id, 500) except musicbrainzngs.ResponseError as e: logger.error('error fetching cover art: %r', e) return if data: with NamedTemporaryFile(suffix='.cover.jpg', delete=False) as f: f.write(data) os.chmod(f.name, 0o644) shutil.move(f.name, cover_art_path) logger.debug('cover art fetched at: %r', cover_art_path) return cover_art_path return
def fetch_cover(release_id, refresh=False): if not os.path.isfile(release_id[0]) or refresh: logger.debug("Hard refreshing cover art for {0}".format(release_id[0])) try: data = musicbrainzngs.get_image_front(release_id[0]) except musicbrainzngs.WebServiceError as exc: logger.error("Error fetching cover art for {0}".format( release_id[0])) logger.error(exc) logger.info('Shutting down') return False try: with open(release_id[0], "wb") as out_file: out_file.write(data) except EnvironmentError: logger.error('Cannot write cover art for {0} to file'.format( release_id[0])) logger.info('Shutting down') return False else: logger.debug("Using pre-fetched cover art for {0}".format( release_id[0])) return True
def downloadAndCacheArtworkFile(tag): album = tag.album artist = tag.artist print("Attempting to download cover for %s %s..." % (album, artist)) result = mb.search_releases(artist=tag.artist, release=tag.album, type='album', format='cd', strict=True) result = result['release-list'] if len(result) == 0: raise "Couldn't find entry for %s %s" % (album, artist) mbid = result[0]['id'] cover = None try: cover = mb.get_image_front(mbid) except: raise "Couldn't find artwork for %s %s" % (album, artist) filename = getCacheFilename(tag) f = open(filename, 'wb') f.write(cover) f.close() print("Downloaded.") resizeImage(filename) print("Resized.") return filename
def _fetch_from_musicbrainz(album: Album, width: int) -> Optional[str]: """ Looks up the album and artist on musicbrainz and fetches the front cover album art for it. :param album: The album to find the cover for. :return: The filename of the downloaded image if one was found. """ releases = mb.search_releases(artist=album.artist_name, release=album.name, limit=10)['release-list'] filename = get_image_path(album, width) with open(filename, 'wb') as f: cover = None i = 0 while not cover and i < len(releases): try: cover = mb.get_image_front(releases[i]['id'], size=width) except mb.ResponseError: i += 1 if cover: f.write(cover) return filename if cover else None
def get_cover_art_as_data(id): '''Gets cover art as binary data if not already stored.''' global cover_art_dict if id in cover_art_dict: return cover_art_dict[id] try: cover_art_dict[id] = musicbrainzngs.get_image_front(id).encode('base64') except musicbrainzngs.musicbrainz.ResponseError: cover_art_dict[id] = '' return cover_art_dict[id]
def getMusicBrainzReleaseID(self, imageSearch=False): #Here we setup our useragent for the webqueries musicbrainzngs.set_useragent('CS3030MusicApp', 'V0.5') #we construct a query string from existing metadata if(self.album != '' and self.artist != ''): temp = '{0} AND artist:{1}'.format(self.album, self.artist) elif(self.album != ''): temp = '"{}"'.format(self.album) elif(self.artist != '' and self.title != ''): temp = '{0} AND artist:{1}'.format(self.title.replace(' ', '_'), self.artist) else: print('Insufficient MetaData for {}'.format(self.filename)) return '' print('Looking for online profile for {}'.format(self.title)) #if there is enough information to create a viable query string, we search the musicBrainz database results = musicbrainzngs.search_releases(query=temp, limit=50) #if any of the results are produced by the same artist, the id is saved for release in results['release-list']: #we try to get a succesful response from the database without any HTTP errors try: musicbrainzngs.get_image_front(release['id']) hasImage = True #if it doesn't work we move on to the next result except: hasImage = False if((release['title'].lower() == self.album.lower()) and hasImage): print('Release match found!') return release['id'] # If nothing is found in releases try recordings but not if the function is called for album art if not imageSearch: self.updateMetaDataInteractive() return '' else: #if nothing is returned we print a notification to console print('No viable database results available for {}'.format(self.album)) return ''
def fetch_musicbrainz_art(album: Album): releases = mb.search_releases(artist=album.artist.name, release=album.name, limit=10)['release-list'] cover = None i = 0 while not cover and i < len(releases): try: cover = mb.get_image_front(releases[i]['id']) except mb.ResponseError: i += 1 if cover: return io.BytesIO(cover)
def getMusicBrainzArt(release): try: image = musicbrainzngs.get_image_front(release["id"], size="250") return image except musicbrainzngs.ResponseError as err: if err.cause.code == 404: log("ERROR. Image not found") else: log("ERROR. Received bad response from the MB server") return None
def find_art(self, artist, album): print("Musicbrainz: find_art:", artist, album) """ Search for the album and then identify the best match Algorithm for chosing the right album: put the search results into a table, search and sort the table accordingly 1. Highest ex-score, highest fuzzy match of album and artist -weighted towards the alnum 2. Best match on Artist name 3. Best match on Album 4. Album type could be used but some will be compilations?? """ ALBUM_MATCH_WEIGHT = 1.5 d = musicbrainzngs.search_release_groups(artist + ' ' + album) albums = [] for k in d['release-group-list']: a = {} if 'id' in k and 'title' and 'artist-credit' and 'ext:score': print("Musicbrainz: find_art: looking for", k['title']) if self.coverart_exists(k['id']): a['id'] = k['id'] else: continue a['score'] = int(k['ext:score']) a['title'] = k['title'] a['match'] = ALBUM_MATCH_WEIGHT * fuzz.token_sort_ratio( a['title'], album) + a['score'] for n in k['artist-credit']: if 'name' in n: a['name'] = n['name'] a['match'] += fuzz.token_sort_ratio(a['name'], artist) print(a) albums.append(a) best_match = 0 best_id = '' for a in albums: if a['match'] > best_match: best_id = a['id'] if best_match > 200: imagebin = musicbrainzngs.get_image_front(best_id) print("Image successfully found, match score was", best_match) return imagebin else: return None
def getAlbumArtwork(musicbrainzalbumid, artwork=None): if not artwork: artwork = {} #get fanart.tv artwork for album artwork = getfanartTVimages("album",musicbrainzalbumid,artwork) #get album info on theaudiodb (and use as spare for artwork) try: audiodb_url = 'http://www.theaudiodb.com/api/v1/json/193621276b2d731671156g/album-mb.php?i=%s' %musicbrainzalbumid response = requests.get(audiodb_url) except Exception as e: logMsg("getMusicArtworkByDbId AudioDB lookup failed --> " + str(e), 0) return {} if response and response.content: data = json.loads(response.content.decode('utf-8','replace')) if data and data.get("album") and len(data.get("album")) > 0: adbdetails = data["album"][0] if not artwork.get("folder") and adbdetails.get("strAlbumThumb"): artwork["folder"] = adbdetails.get("strAlbumThumb") if not artwork.get("discart") and adbdetails.get("strAlbumCDart"): artwork["discart"] = adbdetails.get("strAlbumCDart") if not artwork.get("info") and adbdetails.get("strDescription" + KODILANGUAGE.upper()): artwork["info"] = adbdetails.get("strDescription" + KODILANGUAGE.upper()) if not artwork.get("info") and adbdetails.get("strDescriptionEN"): artwork["info"] = adbdetails.get("strDescriptionEN") if not artwork.get("thumb") and not artwork.get("folder") and not WINDOW.getProperty("SkinHelper.TempDisableMusicBrainz"): try: new_file = "special://profile/addon_data/script.skin.helper.service/musicart/%s.jpg" %musicbrainzalbumid thumbfile = m.get_image_front(musicbrainzalbumid) if thumbfile: f = xbmcvfs.File(new_file, 'w') f.write(thumbfile) f.close() artwork["folder"] = new_file except: pass if not artwork.get("thumb") and not artwork.get("folder") and not WINDOW.getProperty("SkinHelper.TempDisableMusicBrainz"): try: new_file = "special://profile/addon_data/script.skin.helper.service/musicart/%s.jpg" %musicbrainzalbumid thumbfile = m.get_release_group_image_front(musicbrainzalbumid) if thumbfile: f = xbmcvfs.File(new_file, 'w') f.write(thumbfile) f.close() artwork["folder"] = new_file except: pass return artwork
def getAlbumArtwork(self): print( 'Searching Music Brainz database for album artwork\n This could take several minutes...' ) for song in self.songs: #we should skip any files that don't have the appropriate metadata if (song.artist == '' or song.album == ''): print('Skipping {}'.format(song.filename)) continue artworkFolder = os.path.join(self.homeDirectory, 'Album Artwork--') artistFolder = os.path.join(artworkFolder, song.artist + '--') song.artworkPath = os.path.join(artistFolder, song.album + '.jpg') #if album artwork already exists, we continue to the next song if (not os.path.exists(artworkFolder)): os.mkdir(artworkFolder) if (not os.path.exists(artistFolder)): os.mkdir(artistFolder) if (not os.path.exists(song.artworkPath)): print('Searching: {}'.format(song.album)) #we first initiate a search query to find the database id for the album in question song.MBID = song.getMusicBrainzReleaseID(imageSearch=True) #If the song search comes back with an ID we continue if (song.MBID != ''): #then we lookup the artwork using the song's release id and download the raw data try: print('Downloading the image file to {}'.format( song.artworkPath)) rawAlbumArt = musicbrainzngs.get_image_front(song.MBID) #we open a .jpg file and write the binary data to the file file = open(song.artworkPath, 'wb') file.write(rawAlbumArt) file.close() except Exception as ex: print('Problems downloading artwork: {}'.format(ex)) continue #else we create a placeholder file that prevents further search attempts else: file = open(song.artworkPath, 'wb') file.write(b'NO ARTWORK FOUND') file.close() self.dataBase.updateEntry(song)
def front_cover(self, release): """Return the front cover, or None. Tries the release first, then the release group. Returns the image's bytes. """ try: return mb_client.get_image_front(release['id']) except mb_client.ResponseError as e: if isinstance(e.cause, HTTPError) and e.cause.code == 404: pass # no front cover else: raise MusicBrainzError from e try: return mb_client.get_release_group_image_front(release['group-id']) except mb_client.ResponseError as e: if isinstance(e.cause, HTTPError) and e.cause.code == 404: pass # no front cover else: raise MusicBrainzError from e return None
def save_cover_art(release, max_retries=3): """Save the front cover image for the release `release`. Return the saved image's ID, or None if the image isn't available.""" if release['cover-art-archive']['front'] == 'false': return None for retry in range(max_retries): try: image_data = musicbrainzngs.get_image_front(release['id'], size="500") return image.save(image_data, 'catalog') except ResponseError as err: if err.cause.code == 404: # image doesn't exist break elif err.cause.code == 503: print('rate limit exceeded: retrying in {} seconds.'.format( RETRY_SECS)) time.sleep(RETRY_SECS) except NetworkError: break return None
def tag_file(song_file): musicbrainzngs.auth(BRAINZ_USER, BRAINZ_PASS) musicbrainzngs.set_useragent("Auto tag script", "0.1", "http://localhost") #song = path.join(MP3_DIR, '3.mp3') print song_file for score, recording_id, title, artist in acoustid.match( APIKEY, song_file): # Get song data result_data = musicbrainzngs.get_recording_by_id( recording_id, includes=['artists', 'releases']) title = result_data['recording']['title'] artist = result_data['recording']['artist-credit-phrase'] print "%s - %s" % (title, artist) # Set ID3 tags audiofile = eyed3.load(song_file) audiofile.tag.artist = unicode(artist) audiofile.tag.title = unicode(title) # Get Cover Art if result_data['recording']['release-count']: try: imagedata = musicbrainzngs.get_image_front( result_data['recording']['release-list'][0]['id']) print audiofile.tag.images.set( eyed3.id3.frames.ImageFrame.FRONT_COVER, imagedata, 'image/jpeg') cover = open( path.join( COVER_DIR, result_data['recording']['release-list'][0]['title'] + '.jpg'), "w+") cover.write(imagedata) print "---" except musicbrainzngs.musicbrainz.ResponseError: pass audiofile.tag.save()
filename = f"{release['date'].split('-')[0]};{release['title']};{genre}.png" correct_path = f"{subdirectory}/{dont_fuck_up_path(filename)}" # check if file with filename exists -> was already saved before if path.exists(correct_path): print( "SKIIIIIP : RELEASE WAS ALREADY SAVED BEFORE!!" ) continue except KeyError: print( "SKIIIIIP : RELEASE DOES NOT HAVE DATE OR TITLE" ) continue # donwload image try: art = brainz.get_image_front(release['id'], size=250) image = Image.open(io.BytesIO(art)) except brainz.ResponseError: print("SKIIIIIP : ARTWORK IS NOT AVAIABLE IN 250") continue except brainz.NetworkError: print("SKIIIIIP : NETWORK ERROR.") continue try: image.save(correct_path) print("FILE SAVED") except: print("UNKNOWN ERROR OCCURED!!!") continue # reset variables release_offset += release_limitsize
def parse(self, relnum): if not self.mblist: self.mblist = {'manual': 'manual'} #lazy bugfix is lazy for k in self.mblist: if k == 'disc': data = self.mblist['disc']['release-list'][relnum] self.infodict = { 'artist': data['artist-credit-phrase'], 'album': data['title'], 'discnum': '',\ 'multidisc': False, 'date': data['date'], 'relid': data['id'], \ 'infotype': 'musicbrainz', 'tracklist': []} if int(data['medium-count']) > 1: self.infodict['multidisc'] = True for x in data['medium-list']: for y in x['disc-list']: if str(self.disc) == y['id']: self.infodict['discnum'] = x['position'] dindex = int(self.infodict['discnum']) - 1 for x in data['medium-list'][dindex]['track-list']: self.infodict['tracklist'].append(x['recording']['title']) break elif k == 'cdstub': data = self.mblist['cdstub'] self.infodict = { 'artist': data['artist'], 'album': data['title'], 'date': '0000',\ 'discnum': '1', 'multidisc': False, 'relid': data['id'], \ 'infotype': 'cdstub', 'tracklist': []} for x in data['track-list']: self.infodict['tracklist'].append(x['title']) break else: self.infodict = { 'artist': 'Artist', 'album': 'Album Title', 'date': '0000', 'discnum': '1',\ 'multidisc': False, 'relid': 'helpmeihavenoentryonmusicbrainz', 'infotype': 'manual', 'tracklist': []} for x in range(len(self.disc.tracks)): self.infodict['tracklist'].append(f'Track {(x+1):02d}') break try: imageinfo = False imagelist = musicbrainzngs.get_image_list(self.infodict['relid']) for x in imagelist['images']: if x['front']: imageinfo = x except Exception as e: print(e) if os.path.exists(f"{temppath}/{self.infodict['relid']}"): shutil.rmtree(f"{temppath}/{self.infodict['relid']}") os.makedirs(f"{temppath}/{self.infodict['relid']}") if imageinfo: self.infodict[ 'cover'] = f"{temppath}/{self.infodict['relid']}/cover{imageinfo['image'][-4:]}" coverart = open(self.infodict['cover'], 'wb') coverart.write( musicbrainzngs.get_image_front(self.infodict['relid'])) coverart.close() else: self.infodict['cover'] = False print("Couldn't find cover art for this release.") return (self.infodict)
rm *.aiff ''' os.system( 'cdparanoia -Bf; count=1; for i in $(ls); do ffmpeg -i $i ${count}.flac && ((count++)); done; rm *.aiff' ) songs = os.listdir() # add the appropriate tags to each track, then rename each track to the track's album listing for song in songs: os.system( f"lltag --yes -t '{disc_info['tracks'][int(song[:-5]) - 1]}' -a '{disc_info['artist']}' -A '{disc_info['title']}' -n '{int(song[:-5])}' --flac {song}" ) os.system(f"mv -v {song} '{disc_info['tracks'][int(song[:-5]) - 1]}'.flac") # create a png image file of the front cover art if args.cover_art: try: image = mb.get_image_front(release_id) with open('cover.png', 'wb') as file: file.write(image) # set the cover art as the tracks' picture value value os.system(f'metaflac --import-picture-from=cover.png *.flac') print('Applied cover art ...') except: print('No cover art found...') pass # eject the CD from the optical drive os.system('eject /dev/sr0')
def get_cover_art_as_data(id): '''Gets cover art as binary data if not already stored.''' try: return musicbrainzngs.get_image_front(id).encode('base64') except musicbrainzngs.musicbrainz.ResponseError: return ''