#!/usr/bin/python3 import musicbrainzngs import re import time from datetime import date musicbrainzngs.set_useragent( "python-musicbrainzngs-example", "0.1", "https://github.com/dageyev/", ) # WORK IN PROGRESS def get_release_data(rec_id): # todo: ability to choose release and fetch associated data pass def get_rec_data(rec_id, artist_id): recording = musicbrainzngs.get_recording_by_id(rec_id, includes=["isrcs", "place-rels", "artist-rels", "artists", "releases"])['recording'] video = True if 'video' in recording and recording['video'] == 'true' else False if video: parent_rec = next((x['target'] for x in recording['recording-relation-list'] if x['type'] == "music video"), None) recording = musicbrainzngs.get_recording_by_id(parent_rec, includes=["isrcs", "place-rels", "releases"])['recording'] rec_countries = [] master_country = None if 'place-relation-list' in recording: recorded_at = [x for x in recording['place-relation-list'] if x['type'] == "recorded at"] for i in recorded_at: rec_countries.append(get_country_by_place(i['place']['id'])) # or is it "engineered at"? mastered_at = next((x for x in recording['place-relation-list'] if x['type'] == "mixed at"), None) if mastered_at: master_country = get_country_by_place(mastered_at['place']['id']) first_release = get_first_release(recording['release-list']) result = { # check for multiples 'main-artist': recording['artist-credit-phrase'], # 3 'performer-name': None, # 4 'performance-name': recording['title'], # 5 # 6 - figure out exact featuring rules for bands 'instruments': None, # 7 'title': recording['title'], # 9-12 'isrc': recording['isrc-list'][0], # 13 'video': video, # 14 'performed-at': rec_countries[0] if len(rec_countries) > 0 else None, # 16 'recorded-at': rec_countries[0] if len(rec_countries) > 0 else None, # 17 'recorded-at-2': rec_countries[1] if len(rec_countries) > 1 else None, # 18 'recorded-at-3': rec_countries[2] if len(rec_countries) > 2 else None, # 19 'year-of-recording': first_release, # 20 'first-release-date': first_release, # 23 'length': convert_length(int(recording["length"])), # 25 # 26 - figure out exact featuring rules for bands 'mastered-at': master_country # 27 } return result def convert_length(milliseconds): seconds = (milliseconds // 1000) % 60 minutes = (milliseconds // (60 * 1000)) % 60 hours = milliseconds // (60 * 60 * 1000) result = f'{minutes}:{seconds}' if hours: result = f'{hours}:{result}' return result def get_country_by_place(place_id): time.sleep(1) # to avoid being blocked for frequent requests place = musicbrainzngs.get_place_by_id(place_id, includes=['area-rels']) time.sleep(1) # to avoid being blocked for frequent requests area = musicbrainzngs.get_area_by_id(place['place']['area']['id'], includes=['area-rels'])['area'] while area['type'] != "Country": parent = next((x for x in area['area-relation-list'] if x['direction'] == "backward" and x["type"] == "part of"), None) if not parent: return None time.sleep(1) # to avoid being blocked for frequent requests area = musicbrainzngs.get_area_by_id(parent['area']['id'], includes=['area-rels'])['area'] return area["name"] def get_first_release(release_list): # the API has the "first-release-date" field but it's not present in this lib yet result = None for i in release_list: if 'date' in i and re.match(r'\d{4}-\d{2}-\d{2}', i['date']): new_date = date.fromisoformat(i['date']) result = new_date if not result or new_date < result else result return result.isoformat() if result else None if __name__ == '__main__': artist_name = input("Enter artist name\n") artist_list = musicbrainzngs.search_artists(artist=artist_name) result_artists = [[i['name'], i.get('gender', ''), i.get('area', {}).get('name', ''), i.get('disambiguation', '')] for i in artist_list['artist-list']] for count, value in enumerate(result_artists): print(count, value[0], f'({value[1]}, {value[2]}, {value[3]})') artist_number = input("Choose the right artist\n") artist_name = artist_list['artist-list'][int(artist_number)]['name'] artist_id = artist_list['artist-list'][int(artist_number)]['id'] recordings = musicbrainzngs.get_artist_by_id( artist_id, includes=["recording-rels"])['artist']['recording-relation-list'] instruments = None for count, rec in enumerate(recordings): if rec['type'] != 'instrument': rec['instruments'] = rec['type'] print(count, rec['recording']['title'], f'({rec["instruments"]})') else: rec['instruments'] = ', '.join(rec['attribute-list']) print(count, rec['recording']['title'], f'({rec["instruments"]})') rec_number = input("Choose the recording to view extended information\n") recording_id = recordings[int(rec_number)]['recording']['id'] # regular song example # artist_id = 'bb9fe2b7-87fa-43e6-95ca-bc4592d8d5bc' # recording_id = 'abfdc687-7a62-4325-8612-4c6d8b08f486' # music video example # artist_id = 'd24fb461-dee8-41fc-bb15-2f13bb2644a6' # recording_id = 'd3dbb315-951d-40b3-864f-a6b400627f5d' recording = get_rec_data(recording_id, artist_id) recording['instruments'] = recordings[int(rec_number)]['instruments'] recording['performer-name'] = artist_name print(recording)