7.2. Howdy Music API
This document describes the lower level Howdy Music API, upon which the command line tools are built. It lives in howdy.music
.
7.2.1. howdy.music module
This contains only three methods: two format durations strings for YouTube clips, and a third is used to search for M4A music files that are missing artist or album information.
- howdy.music.fill_m4a_metadata(filename, data_dict, verify=True, image_data=None)
Low level method that populates the metadata of an M4A music file.
- Parameters:
data_dict (dict) – a dictionary of candidate music metadata with the following obligatory keys:
song
,album
,artist
,year
,tracknumber
, andtotal tracks
. If the URL of the album image,album url
, is defined, then also provides the album image into the M4A file.image_data (BytesIO) – optional argument. If defined, is a
BytesIO
binary data representation of usually a candidate PNG image file.
- howdy.music.format_youtube_date(dt_duration)
- Parameters:
dt_duration (datetime) – the
datetime
- Returns:
a standard second, or MM:SS (such as 4:33), or so on from a
datetime
returned byparse_youtube_date
.- Return type:
See also
- howdy.music.get_failing_artistalbum(filename)
- howdy.music.get_m4a_metadata(filename)
Low level method that returns the metadata of an M4A music file.
- howdy.music.parse_youtube_date(duration_string)
Parses a duration string that
isodate
can recognize, such asPT4M33S
, into adatetime
.- Parameters:
duration_string (str) – duration in
isodate
format, such asPT4M33S
to represent 4 minutes and 33 seconds.- Returns:
the
datetime
that can be used to infer duration usingformat_youtube_date
.- Return type:
See also
7.2.2. howdy.music.music module
This contains the low-level functionality that does three things.
Gets music metadata using either the Gracenote, LastFM, or MusicBrainz APIs.
Retrieves YouTube clips using the YouTube Google API and yt-dlp.
Note
I checked on
15 OCTOBER 2021
, and I see some disturbing things. The latest version of youtube-dl is6 JUNE 2021
. This discussion on YCombinator says thatYouTube is dead
. Also, when I used the youtube-dl command line or the YoutubeDL API, my download speeds are no faster than 80 kbp/s. This means using yt-dlp.From my cursory work, doing
howdy_music_songs -M -a Air -s "All I Need"
, the old youtube-dl speeds that I loved and got used to seem to work again!Uploads music to one’s own Google Play Music account using GMusicAPI, and sets its credentials.
- class howdy.music.music.HowdyLastFM(data=None, verify=True)
This object uses the LastFM API, through the higher level
musicbrainzngs
Python module, to get information on songs, albums, and artists. Where possible, this extracts additional song metadata using the MusicBrainz API.- Parameters:
data (dict) – optional argument, containg the LastFM API data:
api_key
,api_secret
,application_name
, andusername
. See Section 2.1.4 to understand how to set up the LastFM API credentials. If not given, then gets the LastFM API data fromHowdyLastFM.get_lastfm_credentials
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- Variables:
- get_album_image(artist_name, album_name)
- Parameters:
- Returns:
If successful, downloads the album image into a PNG file named “artist_name.album_name.png”, and returns a two-element
tuple
, whose first element is the PNG filename, and whose second element is the string"SUCCESS"
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- get_album_info(artist_name, album_name)
- Parameters:
- Returns:
a two-element
tuple
, whose first element is adict
of LastFM API low level information on the album, and whose second element is the string"SUCCESS"
. For example, for Moon Safari from Air, we have, complicated JSON structure stored inHowdyLastFM get_album_info
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- classmethod get_album_url(album_url_entries)
Returns the album URL of the largest album image provided.
- Parameters:
album_url_entries (list) – a
list
of album URL information. Each element is adict
with two keys: #text is the URL, and size is a qualifier on the image size – can be one ofmega
,extralarge
,large
,medium
,small
, or “” (no size given).- Returns:
images sizes are ordered this way –
mega
,extralarge
,large
,medium
,small
, and “”. Returns the URL for the largest sized album image in this collection.- Return type:
- get_collection_album_info(album_name)
- Parameters:
album_name (str) – the name of a compilation album (consisting of multiple artists).
- Returns:
a two-element
tuple
, whose first element is adict
of summary information on tracks for this compilation album, and whose second element is the string"SUCCESS"
. This dictionary is a low level LastFM data structure. The example low level, nicely formatted JSON representation of this dictionary, for the compilation album, The Politics of Photosynthesis, is located inlastfm_collection_data.json
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- classmethod get_lastfm_credentials()
- classmethod get_mb_album_year(year_string)
Returns a year of release given a MusicBrainz style date string, can be either of the form “2000-12-23” (YYYY-MM-DD)” or just four-digit year.
- Parameters:
year_string (str) – a MusicBrainz style date string, can be either of the form “2000-12-23” (YYYY-MM-DD) or just four-digit year.
- Returns:
the year corresponding to the release date. If date string is invalid, then returns
None
.- Return type:
- get_music_metadata(song_name, artist_name, all_data=False)
Uses the MusicBrainz API to fill out as much metadata as possible for a given song. Before running this method, one should first set the MusicBrainz API header data with
MusicInfo.get_set_musicbrainz_useragent
.- Parameters:
song_name (str) – name of the song.
artist_name (str) – name of the artist.
all_data (bool) – optional argument. If
False
, then perform a cursory search for metadata on the selected song. IfTrue
, then perform a more careful search. Default isFalse
. Running withTrue
can work if running withFalse
does not produce a result.
- Returns:
if successful, returns a two element
tuple
. First element is adict
of information on the song, and the second element is the string"SUCCESS"
. For example, for the Air song Kelly Watch the Stars in Moon Safari. the closest match isKelly, Watch the Stars!
.{'album': 'Moon Safari', 'artist': 'Air', 'year': 1998, 'tracknumber': 4, 'total tracks': 10, 'song': 'Kelly, Watch the Stars!', 'duration': 225.746, 'album url': 'https://lastfm.freetls.fastly.net/i/u/300x300/016....png'}
If unsuccessful, then returns a
tuple
of formatreturn_error_raw
.- Return type:
Note
LastFM does not provide a release date at all. Furthermore, LastFM documentation shown here (https://www.last.fm/api/show/album.getInfo) is incorrect. See, e.g, pylast/pylast#177 and feross/last-fm#2.
- get_music_metadatas_album(artist_name, album_name)
- Parameters:
- Returns:
a two-element
tuple
, whose first element is alist
of summary information on tracks for this album, and whose second element is the string"SUCCESS"
. The elements in this list are ordered by first song track to last song track. An example first song for the Moon Safari album released by Air is,{'song': 'La Femme D’argent', 'artist': 'Air', 'tracknumber': 1, 'total tracks': 10, 'duration': 429.56, 'album url': 'https://lastfm.freetls.fastly.net/i/u/300x300/016b6....png', 'album': 'Moon Safari', 'year': 1998}
If the album name has not been published by this artist, return a
tuple
of formatreturn_error_raw
.- Return type:
- get_song_listing(artist_name, album_name)
- Parameters:
- Returns:
If successful, returns a two-element
tuple
, whose first element is the list of songs ordered by track number, and whose second element is the string"SUCCESS"
. Each element in this list is atuple
of song number and track number. For example, for Moon Safari by Air,
[("La Femme d'Argent", 1), ('Sexy Boy', 2), ('All I Need', 3), ('Kelly Watch the Stars', 4), ('Talisman', 5), ('Remember', 6), ('You Make It Easy', 7), ('Ce Matin-Là', 8), ('New Star in the Sky (Chanson Pour Solal)', 9), ('Le Voyage De Pénélope', 10)]
If unsuccessful, then returns a
tuple
of formatreturn_error_raw
.- Return type:
- class howdy.music.music.HowdyMusic(verify=True)
This object uses the Gracenote API to get information on songs, albums, and artists. Uses
HowdyMusic.get_gracenote_credentials
to get the Gracenote API configuration data.- Parameters:
verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.- Variables:
- Raises:
ValueError – if cannot find the Gracenote API configuration information in the database.
Warning
As of October 20, 2019, this API may not be generally functional. A discussion is found on the Pygn Python Gracenote API implementation, cweichen/pygn#14.
- get_album_image(artist_name, album_name)
- Parameters:
- Returns:
If successful, downloads the album image into a PNG file named “artist_name.album_name.png”, and returns a two-element
tuple
, whose first element is the PNG filename, and whose second element is the string"SUCCESS"
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- classmethod get_gracenote_credentials()
- Returns:
a
tuple
of Gracenote API clientID and userID from the SQLite3 configuration database.- Raises:
ValueError – if cannot find the Gracenote_API configuration information in the database.
- get_music_metadata(song_name, artist_name)
- Parameters:
- Returns:
if successful, returns a two element
tuple
. First element is adict
of information on the song, and the second element is the string"SUCCESS"
. For example, for the Air song Kelly Watch the Stars in Moon Safari,{'album': 'Moon Safari', 'artist': 'Air', 'year': 1998, 'tracknumber': 4, 'total tracks': 10, 'song': 'Kelly, Watch the Stars!', 'duration': 225.746, 'album url': 'https://lastfm.freetls.fastly.net/i/u/300x300/016b6b....png'}
If unsuccessful, then returns a
tuple
of formatreturn_error_raw
.- Return type:
- get_music_metadata_lowlevel(metadata_song, album_title=None)
- Parameters:
- Returns:
if successful, returns a two element
tuple
. First element is adict
of information on the song, and the second element is the string"SUCCESS"
. This dictionary defines the following keys:song
,artist
,tracknumber
,total tracks
,year
,album url
, andalbum
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- get_music_metadatas_album(artist_name, album_name)
- Parameters:
- Returns:
a two-element
tuple
, whose first element is alist
of summary information on tracks for this album, and whose second element is the string"SUCCESS"
. The elements in this list are ordered by first song track to last song track. An example first song for the Moon Safari album released by Air is,{'song': 'La Femme D’argent', 'artist': 'Air', 'tracknumber': 1, 'total tracks': 10, 'duration': 429.56, 'album url': 'https://lastfm.freetls.fastly.net/i/u/300x300/016b6....png', 'album': 'Moon Safari', 'year': 1998}
If the album name has not been published by this artist, return a
tuple
of formatreturn_error_raw
.- Return type:
- get_song_listing(artist_name, album_name)
- Parameters:
- Returns:
a
list
of songs ordered by track number, and whose second element is the string"SUCCESS"
. Each element in this list is atuple
of song number and track number. For example, for Moon Safari by Air,[("La Femme d'Argent", 1), ('Sexy Boy', 2), ('All I Need', 3), ('Kelly Watch the Stars', 4), ('Talisman', 5), ('Remember', 6), ('You Make It Easy', 7), ('Ce Matin-Là', 8), ('New Star in the Sky (Chanson Pour Solal)', 9), ('Le Voyage De Pénélope', 10)]
- Return type:
- classmethod push_gracenote_credentials(client_ID, verify=True)
Pushes the Gracenote API configuration into the SQLite3 configuration database.
- Parameters:
- Raises:
ValueError – if the
client_ID
is invalid, or cannot update the database.
- class howdy.music.music.MusicInfo(artist_name, artist_mbid=None, do_direct=False)
This object uses the MusicBrainz API, through the higher level
musicbrainzngs
Python module, to get information on songs, albums, and artists.- Parameters:
artist_name (str) – the artist over which to search.
artist_mbid (str) – optional argument. If not
None
, then information on this artist uses this MusicBrainz artist ID to get its info. Default isNone
.do_direct (bool) – optional argument. If
True
, then perform a direct search on the artist rather than using the default indexed search at a low lebvel. Default isFalse
. See :py:meth`get_artist_direct_search_MBID <howdy.music.music.MusicInfo.get_artist_direct_search_MBID>` for the low-level functionality.
- Variables:
artist (dict) –
the low level information on a specific artist, returned by
musicbrainzngs
. For example, for the artist Air, this looks like,{'id': 'cb67438a-7f50-4f2b-a6f1-2bb2729fd538', 'type': 'Group', 'ext:score': '100', 'name': 'Air', 'sort-name': 'Air', 'country': 'FR', 'area': {'id': '08310658-51eb-3801-80de-5a0739207115', 'type': 'Country', 'name': 'France', 'sort-name': 'France', 'life-span': {'ended': 'false'}}, 'begin-area': {'id': '2322e571-1d9b-4023-a31c-7222509407ab', 'type': 'City', 'name': 'Versailles', 'sort-name': 'Versailles', 'life-span': {'ended': 'false'}}, 'disambiguation': 'French band', 'isni-list': ['0000000123694584'], 'life-span': {'begin': '1995', 'ended': 'false'}, 'alias-list': [ {'sort-name': 'Air French Band', 'alias': 'Air French Band'}, {'sort-name': 'Air (French Band)', 'alias': 'Air (French Band)'}, {'sort-name': 'Aïr', 'alias': 'Aïr'}], 'tag-list': [{'count': '2', 'name': 'trip-hop'}, {'count': '10', 'name': 'electronic'}, {'count': '7', 'name': 'downtempo'}, {'count': '0', 'name': 'soundtrack'}, {'count': '0', 'name': 'pop'}, {'count': '2', 'name': 'chillout'}, {'count': '5', 'name': 'ambient'}, {'count': '0', 'name': 'jazz'}, {'count': '7', 'name': 'french'}, {'count': '1', 'name': 'idm'}, {'count': '0', 'name': 'france'}, {'count': '0', 'name': 'français'}, {'count': '3', 'name': 'electronica'}, {'count': '0', 'name': 'producer'}, {'count': '0', 'name': 'composer'}, {'count': '0', 'name': 'lyricist'}, {'count': '0', 'name': 'european'}, {'count': '0', 'name': 'parolier'}, {'count': '0', 'name': 'compositeur'}, {'count': '0', 'name': 'producteur'}, {'count': '0', 'name': 'dance and electronica'}, {'count': '2', 'name': 'ambient pop'}]}
artist_name (str) – the artist’s name.
ambid (int) – the MusicBrainz artist ID.
alltrackdata (dict) –
the low-level
dict
of information on all studio albums produced by the artist. Each key in this top level dictionary is a studio album. Each value is a lower level dictionary of summary information on that album, with the following keys.release-date
is thedate
when that album was released.album-url
if defined, is the URL to the album’s image. If not defined, then it is an emptystr
.tracks
is adict
of tracks on this album. Each key is the track number, and each value is atuple
of song name, and song length.
For example, here is information on the Moon Safari album released by Air.
{'release-date': datetime.date(1998, 1, 16), 'album url': '', 'tracks': {1: ('La Femme D’argent', 429.56), 2: ('Sexy Boy', 298.466), 3: ('All I Need', 268.333), 4: ('Kelly, Watch the Stars!', 225.746), 5: ('Talisman', 256.48), 6: ('Remember', 154.293), 7: ('You Make It Easy', 240.826), 8: ('Ce Matin-Là', 218.506), 9: ('New Star in the Sky (Chanson Pour Solal)', 340.8), 10: ('Le Voyage De Pénélope', 190.866)}}
- get_album_image(album_name)
- Parameters:
album_name (str) – album_name.
- Returns:
If successful, downloads the album image into a PNG file named “artist_name.album_name.png”, and returns a two-element
tuple
, whose first element is the PNG filename, and whose second element is the string"SUCCESS"
. If unsuccessful, then returns atuple
of formatreturn_error_raw
.- Return type:
- classmethod get_album_info(album)
- Parameters:
album (dict) – a dictionary of low-level album info returned by
musicbrainzngs
associated with this studio album.- Returns:
a two-element
tuple
if successful, otherwise returnsNone
. The first is the studio album name, and each second element is adict
containing summary album info of that album. See thealtrackdata
dictionary inMusicInfo
to understand the description of summary album information.- Return type:
- classmethod get_albums_lowlevel(ambid, do_all=False)
Used by the constructor to get the collection of studio albums released by this artist.
- Parameters:
ambid (int) – the MusicBrainz artist ID.
do_all (bool) – if
True
, then return all the MusicBrainz album info provided. IfFalse
, then do not include albums that have been classified as remixes or mixtapes. Default isFalse
.
- Returns:
a
list
, where each element of the list is low-levelmusicbrainzngs
music collection information. The album information is adict
with the following keys,id
is the MusicBrainz album ID.type
is the type of the release (for example,Album
s a studio released album).title
is the name of the release.first-release-date
is the release date, as astr
.primary-type
is the main type of the release.
For example, for the artist Air, whose MusicBrainz artist ID is
"cb67438a-7f50-4f2b-a6f1-2bb2729fd538"
, an example first element in the list is,{'id': 'b0bf2b77-b8cf-32f6-8893-9741d757b400', 'type': 'Album', 'title': 'Moon Safari', 'first-release-date': '1998-01-16', 'primary-type': 'Album'}
- Return type:
- classmethod get_artist_datas_LL(artist_name, min_score=100, do_strict=True, artist_mbid=None, do_direct=False)
- Parameters:
artist_name (str) – the artist over which to search.
min_score (int) – optional argument. Filter on this minimum score on artist name matches to
artist_name
. 0 \(\le\)min_score
\(\le 100\). Default is100
.do_strict (bool) – optional argument. If
True
, performs a strict search using themusicbrainzngs search_artists
method. Default isTrue
.artist_mbid (str) – optional argument. If not
None
, then uses musicbrainzngs’sget_artist_by_id
to get information on an artist. Otherwise, gets all artist matches. Default isNone
.do_direct (bool) – Sometimes the MusicBrainz server does not update. Fixes-when-broken of the MusicBrainz server do not happen on a schedule, or even a quickness. In such an instance, you can specify the specific artist using direct search rather than indexed search. See :py:meth`get_artist_direct_search_MBID <howdy.music.music.MusicInfo.get_artist_direct_search_MBID>`.
- Returns:
a
list
of artist information matches toartist_name
. Ifartist_mbid
is notNone
, then gets a SINGLE artist match. Otherwise gets all matches found.- Return type:
- classmethod get_artist_direct_search_MBID(artist_name)
Sometimes the MusicBrainz server does not update. Fixes-when-broken of the MusicBrainz server do not happen on a schedule, or even a quickness. In such an instance, you can specify the specific artist using direct search rather than indexed search. This method returns the artist’s MBID of the artist one queries. If there is more than one match, then returns
None
.- Parameters:
artist_name (str) – the artist over which to perform a search.
- Returns:
the MBID of the artist. If more than one matching artist is found, or no matching artists, then returns
None
.
- get_music_metadata(song_name, min_criterion_score=85)
- Parameters:
song_name (str) – name of the song.
min_criterion_score (int) – the minimum score to accept for a string similarity comparison between
song_name
and any track created by this artist.70
\(\le\)min_criterion_score
\(\le\)100
, and the default is85
. Theget_maximum_matchval
performs the string comparison. If no track matchessong_name
, then track data for a track that is the closest match (while having a similarity score \(\ge\)min_criterion_score
) tosong_name
is returned.
- Returns:
if successful, a two element
tuple
. First element is adict
of information on the song, and the second element is the string"SUCCESS"
. For example, for the Air song Kelly Watch the Stars in Moon Safari, the closest match isKelly, Watch the Stars!
.{'album': 'Moon Safari', 'artist': 'Air', 'year': 1998, 'tracknumber': 4, 'total tracks': 10, 'song': 'Kelly, Watch the Stars!', 'duration': 225.746, 'album url': 'http://...2-490838855977/21141679576.jpg'}
If unsuccessful, then returns a
tuple
of formatreturn_error_raw
.- Return type:
- get_music_metadatas_album(album_name, min_criterion_score=95)
- Parameters:
album_name (str) – a studio album released by this artist.
min_criterion_score (int) – the minimum score to accept for a string similarity comparison between
album_name
and any studio album created by this artist.70
\(\le\)min_criterion_score
\(\le\)100
, and the default is95
. Theget_maximum_matchval
performs the string comparison. If no album matchesalbum_name
, then return album data for the album whose name is closest (while having a similarity score \(\ge\)min_criterion_score
) toalbum_name
is returned.
- Returns:
a two-element
tuple
, whose first element is alist
of summary information on tracks for this album, and whose second element is the string"SUCCESS"
. The elements in this list are ordered by first song track to last song track. An example first song for the Moon Safari album released by Air is,{'artist': 'Air', 'album': 'Moon Safari', 'year': 1998, 'total tracks': 10, 'song': 'La Femme D’argent', 'tracknumber': 1, 'album url': '', 'duration': 429}
If the album name has not been published by this artist, return a
tuple
of formatreturn_error_raw
.- Return type:
- classmethod get_set_musicbrainz_useragent(email_address)
- Parameters:
email_address (str) – a valid email address to provide to provide to the MusicBrainz API’s user agent.
- Returns:
a
dict
whose two keys and values are,appname
is the application name registered with the MusicBrainz API.version
is the application version.
This information comes from the SQLite3 configuration database.
- Return type:
- Raises:
ValueError – if the MusicBrainz API configuration information cannot be found.
- get_song_listing(album_name)
- Parameters:
album_name (str) – album_name.
- Returns:
If successful, returns a two-element
tuple
, whose first element is the list of songs ordered by track number, and whose second element is the string"SUCCESS"
. Each element in this list is atuple
of song number and track number. For example, for Moon Safari by Air,[("La Femme d'Argent", 1), ('Sexy Boy', 2), ('All I Need', 3), ('Kelly Watch the Stars', 4), ('Talisman', 5), ('Remember', 6), ('You Make It Easy', 7), ('Ce Matin-Là', 8), ('New Star in the Sky (Chanson Pour Solal)', 9), ('Le Voyage De Pénélope', 10)]
If unsuccessful, then returns a
tuple
of formatreturn_error_raw
.- Return type:
- print_format_album_names()
Pretty-prints summary table of studio albums released by the artist, ordered by album release date. For example, for Air,
Air has 7 studio albums. Studio Album Year # Tracks --------------------------------- ------ ---------- Moon Safari 1998 10 10 000 Hz Legend 2001 12 City Reading (Tre Storie Western) 2003 19 Talkie Walkie 2004 11 Pocket Symphony 2006 12 Love 2 2009 12 Music for Museum 2014 9
- classmethod push_musicbrainz_useragent(appname, version)
Pushes the MusicBrainz API configuration into the SQLite3 configuration database.
- Parameters:
appname (str) – the application name registered with the MusicBrainz API.
version (str) – the application version.
- classmethod set_musicbrainz_verify(verify=True)
Makes the MusicBrainz API to use either HTTPS (if verifying traffic) or HTTP (if not verifying traffic)
- Parameters:
verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- howdy.music.music.download_best_song(artist_name, song_name, youtube=None, verify=True)
If successful, downloads the most likely YouTube clip into an M4A file, whose name is
"artist_name"."song_name".m4a
. Uses the LastFM API functionality, throughHowdyLastFM
, to get the music metadata.- Parameters:
artist_name (str) – the artist name.
song_name (str) – name of the song.
youtube (Resource) – optional aegument, a googleapiclient Resource object that allows for the access to the YouTube Google API. If not defined, then instantiated with
get_youtube_service
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- Returns:
if successful, the file name of the downloaded M4A song (
"artist_name"."song_name".m4a
). If cannot find the song metadata, or cannot find YouTube clips for this song, then returnsNone
.
- howdy.music.music.get_gmusic_all_songs(verify=True, device_id=None)
Returns a
dict
of all songs stored on one’s Google Play Music account. Each key is an unique song ID, and each value is summary information for that song. Example element output looks like,{'kind': 'sj#track', 'id': 'fe65be9b-5e0d-39f8-a104-34579cac7d25', 'clientId': '0xjqU3q/jCIkKK+42LXx+A', 'creationTimestamp': '1312046208050197', 'lastModifiedTimestamp': '1385273200005040', 'recentTimestamp': '1312050096197000', 'deleted': False, 'title': "Why Can't There Be Love (Pilooski Edit)", 'artist': 'Pilooski', 'composer': 'Hermon Weems', 'album': 'Saint-Germain-Des-Pres Cafe (The Blue Edition)', 'albumArtist': 'Saint-Germain-Des-Prés Café (Selected and mixed by Mr Scruff)', 'year': 2010, 'comment': '', 'trackNumber': 15, 'genre': 'Dance & DJ', 'durationMillis': '180720', 'beatsPerMinute': 0, 'albumArtRef': [{'kind': 'sj#imageRef', 'url': 'http://lh5.ggpht.com/Czw3aqGNeQdsXMy9EnaAoC92F3WZHvKO2iqRGyZouUodlJqTP3anpjxb7qdLTdsPae1evBD0'}], 'playCount': 0, 'totalTrackCount': 0, 'discNumber': 0, 'totalDiscCount': 0, 'rating': '0', 'estimatedSize': '5782883', 'storeId': 'Tovfqdqypwu27btjcetswr464qe', 'albumId': 'B4utisa64lnb5bja5hg3ym5efrm', 'artistId': ['A5yefhy34gybvo5okv4hfychfia'], 'nid': 'Tovfqdqypwu27btjcetswr464qe'}
If cannot access the account, returns
None
.- Parameters:
- Raises:
ValueError – if cannot find and use the correct device ID.
- howdy.music.music.get_gmusicmanager(useMobileclient=False, verify=True, device_id=None)
Returns a GmusicAPI manager used to perform operations on one’s Google Play Music account. If the Musicmanager is instantiated but cannot find the device (hence properly authorize for operation), then the attribute
error_device_ids
is a non-emptyset
of valid device IDs.- Parameters:
useMobileClient (bool) – optional argument. If
True
, use theMobileClient
manager, otherwise use theMusicmanager
manager. Default isFalse
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.device_id (str) – optional argument. If defined, then attempt to use this MAC ID to register the music manager.
- Raises:
ValueError – if cannot instantiate the Musicmanager.
AssertionError – if cannot get machine’s MAC id.
See also
- howdy.music.music.get_youtube_file(youtube_URL, outputfile, use_aria2c=True)
Uses youtube-dl programmatically to download into an M4A file.
- howdy.music.music.get_youtube_service(verify=True)
Gets the YouTube Google API service from the Google OAuth2 credentials stored in the SQLite3 configuration database.
- Parameters:
verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.- Returns:
a googleapiclient Resource object that allows for the access to the YouTube Google API.
- howdy.music.music.gmusicmanager(useMobileclient=False, verify=True, device_id=None)
Returns a
contextmanager
wrapped GmusicAPI manager used to perform operations on one’s Google Play Music account.- Parameters:
useMobileClient (bool) – optional argument. If
True
, use theMobileClient
manager, otherwise use theMusicmanager
manager. Default isFalse
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.device_id (str) – optional argument. If defined, then attempt to use this MAC ID to register the music manager.
See also
- howdy.music.music.gmusicmanager_fixlogin(mmg)
Workaround to deal with following problem: cannot create an authorized GmusicAPI
Mobileclient
because the device ID automatically found is not one of theset
of authorized device IDs.- Parameters:
mmg (Mobileclient) – the erroring out
Mobileclient
music manager.- Raises:
ValueError – if the music manager has not errored out.
ValueError – if the music manager is not a
Mobileclient
.
See also
- howdy.music.music.oauth_get_google_credentials()
Gets the Google Oauth2 credentials, stored in the SQLite3 configuration database, in the form of a refreshed
AccessTokenCredentials
object. This OAuth2 authentication method IS used only for the GMusicAPI Mobileclient manager.- Returns:
a
AccessTokenCredentials
form of the Google Oauth2 credentials for various Oauth2 services.- Return type:
See also
- howdy.music.music.oauth_store_google_credentials(credentials)
Stores the Google OAuth2 credentials, in the form of a
AccessTokenCredentials
object, into the SQLite3 configuration database for theMobileClient
manager.- Parameters:
credentials – the
AccessTokenCredentials
object to store into the database.
See also
- howdy.music.music.plexapi_music_playlist_info(plex_playlist, use_internal_metadata=False)
This creates a
DataFrame
out of thePlexAPI Playlist
. This DataFrame has the following columns:order in playlist
filename
added date
song name
artist
track number
album
album number of tracks
album year
- Parameters:
plex_playlist (
PlexAPI PlayList
) – thePlexAPI Playlist
, which must be an audio playlist.use_internal_metadata (bool) – if
True
, then fill out columns using the M4A metadata from the file, otherwise fill out the columns using information inplex_playlist
. Default isFalse
.
- Returns:
a DataFrame of useful track information for the playlist.
- Return type:
- howdy.music.music.save_gmusic_creds(email, password)
Pushes one’s Google account email and password into the
gmusic
configuration stored in the SQLite3 configuration database.
- howdy.music.music.upload_to_gmusic(filenames, verify=True)
Uploads a collection of music files to the Google Play Music account.
- howdy.music.music.youtube_search(youtube, query, max_results=10)
Performs a string query to search through YouTube clips, and returns list of valid YouTube URLs.
- Parameters:
youtube (Resource) – a googleapiclient Resource object that allows for the access to the YouTube Google API.
query (str) – the string on which to search.
max_results (int) – optional argument, the maximum number of YouTube clips to return. Must be \(\ge 1\). Default is
10
.
- Returns:
- Return type:
7.2.3. howdy.music.music_spotify module
These module handles integration with the Spotify RESTful API that does the following things:
Methods to handle authentication to the Spotify API. See this blog article on the Spotify Web API on how to set up a Spotify Web API client, and to acquire your client ID and client secret.
Methods to copy the Spotify song ID into an M4A song file’s metadata, and to get the Spotify song ID of the song.
Methods that returns the Spotify ID based on a song’s metadata.
Methods that show, create, modify the current user’s Spotify public playlists.
Methods that convert a
DataFrame
representing a Plex music playlist into aDataFrame
representing a data structure that can be converted into a Spotify public playlist.
In this API I refer to the Spotify ID of a song, which has format :spotify:track:<STRING>
. For example, the song All I Need by Air the French band has a Spotify ID = spotify:track:6T10XPeC9X5xEaD6tMcK6M
. It can be found at https://open.spotify.com/track/6T10XPeC9X5xEaD6tMcK6M.
- howdy.music.music_spotify.create_public_playlist(oauth2_access_token, name, description, my_userid=None)
Creates a new public Spotify playlist for the current user.
- Parameters:
oauth2_access_token (str) – the Spotify access token for the OAuth2-authenticated Spotify API. One needs this token to access, add, delete, and modify Spotify playlists.
name (str) – name of the new playlist.
description (str) – the new playlist’s description.
my_userid (str) – Optional argument, which is the Spotify current user ID. If not specified, then determines the current user ID using the OAuth2-authenticated Spotify API.
- Returns:
status on whether it can create the playlist. If a playlist, with the same name exists, does nothing and returns
False
. Otherwise, if no other public playlist (owned by the current user) exists, creates the playlist and returnsTrue
.- Return type:
- howdy.music.music_spotify.get_existing_track_ids_in_spotify_playlist(spotify_playlist_id, oauth2_access_token)
Low-level method that returns the
list
of Spotify IDs in a public Spotify playlist. Spotify API quirk: can only get the Spotify IDs in units of 100 at most per Spotify API query.
- howdy.music.music_spotify.get_or_push_spotify_oauth2_token()
- howdy.music.music_spotify.get_public_playlists(oauth2_access_token, my_userid=None)
Returns all the Spotify public playlists for the current user.
- Parameters:
oauth2_access_token (str) – the Spotify access token for the OAuth2-authenticated Spotify API. One needs this token to access, add, delete, and modify Spotify playlists.
my_userid (str) – Optional argument, which is the Spotify current user ID. If not specified, then determines the current user ID using the OAuth2-authenticated Spotify API.
- Returns:
a
list
of summary information on the current user’s public Spotify playlists. Each entry is adict
with the following attributes: its name, description, the Spotify ID of the playlist, the Spotify ID of the user who owns the playlist, and the number of songs in the playlist.- Return type:
- howdy.music.music_spotify.get_spotify_credentials()
- howdy.music.music_spotify.get_spotify_session()
Returns the session token from a valid Spotify API account. :rtype: str
- howdy.music.music_spotify.get_spotify_song_id(spotify_access_token, song_metadata_dict, song_limit=5, market='us', dump_response=False, response_file='foo.json')
Heavily-instrumented lower-level method that attempts to find the Spotify ID of a song given its metadata.
- Parameters:
song
is the song title.artist
is the song’s artist.date
is the album’s release date, of typedate
.album
is the song’s album.
- Parameters:
- Returns:
a
str
of various types.
If the underlying Spotify API call fails, then returns the Spotify API error message.
If the Spotify API call is successful, but for some reason cannot find the Spotify ID, returns a message that states.
CANNOT FIND SPOTIFY TRACK ID FOR <SPOTIFY_QUERY>
Where
<SPOTIFY_QUERY>
is the low-level Spotify API query used to search for that song’s Spotify ID.In the best, nominal operation case, returns the Spotify ID.
- Return type:
- howdy.music.music_spotify.get_spotify_song_id_filename(filename)
- howdy.music.music_spotify.modify_existing_playlist_with_new_tracks(spotify_playlist_id, oauth2_access_token, spotify_ids_list, spotify_ids_in_playlist=None)
Lower-level method that replaces the collection of songs in Spotify playlist, identified by
spotify_playlist_id
, with a new collection of Spotify IDs inspotify_ids_list
. Interesting Spotify API wrinkle: one can use the Spotify API to remove as many songs from a playlist as possible; one can use the Spotify API to add songs to a playlist in chunks of at most 100 songs.- Parameters:
oauth2_access_token (str) – the Spotify access token for the OAuth2-authenticated Spotify API. One needs this token to access, add, delete, and modify Spotify playlists.
spotify_ids_list (list) – the new
list
of Spotify IDs corresponding to an updated Spotify playlist.spotify_ids_in_playlist (list) – optional argument. If not specified, then uses
get_existing_track_ids_in_spotify_playlist
to get the list of Spotify IDs for the playlist specified byspotify_playlist_id
. If this is specified, then method assumes that this is the list of Spotify IDs for this playlist.
- howdy.music.music_spotify.process_dataframe_playlist_spotify(df_playlist, spotify_access_token)
Low-level method that takes a
DataFrame
representing a Plex playlist (its schema is described inplexapi_music_playlist_info
) and converts it into aDataFrame
. This returnedDataFrame
has a column representing Spotify ID.For each song it finds in the input playlist,
df_playlist
, it tries to find the Spotify ID.If it finds the Spotify ID in the M4A file’s metadata, returns that.
If not, it queries the song’s title, artist, album, and year. If it finds the Spotify ID then it returns it.
If not, it queries on a modified song title – replacing mentions of “feat” or “Feat” or variations of “featuring”, title, album, and year. If it finds the Spotify ID then it returns it.
If not, it queries on the modified song title, artist, and album. If it find the Spotify ID then it returns it.
If not, it queries on the modified song title and artist. If it finds the Spotify ID then it returns it.
Finally, if not, returns the error message associated with the above query or other Spotify API error message.
- Parameters:
- Returns:
the DataFrame with an extra
string
column, namedSPOTIFY ID
. Its value is either a valid Spotify ID or other error message.- Return type:
See also
- howdy.music.music_spotify.process_dataframe_playlist_spotify_bads(df_playlist_spotify, spotify_access_token)
Necessary method to purify the collection of songs for which we do not have Spotify IDs. For those songs that do not have valid Spotify IDs, it uses the Spotify API to try to find valid Spotify IDs. For each song it tries, if it does find a valid ID, it pushes that ID into the song file (using
push_spotify_song_id_to_file
).
- howdy.music.music_spotify.process_dataframe_playlist_spotify_multiproc(df_playlist, spotify_access_token, numprocs=12)
Method that chunks out the identification of Spotify IDs from a Plex playlist among multiple processors. It uses
process_dataframe_playlist_spotify
on each processor chunk of the input Plex music playlistDataFrame
.- Parameters:
- Returns:
the DataFrame with an extra
string
column, namedSPOTIFY ID
. Its value is either a valid Spotify ID or other error message.- Return type:
See also
- howdy.music.music_spotify.push_spotify_credentials(client_id, client_secret, verify=True)
Pushes the Spotify API configuration into the SQLite3 configuration database. Take a look at this blog article on the Spotify API for some more information on setting up your Spotify web API client.
7.2.4. howdy.music.pygn module
This contains functionality used by the HowdyMusic
higher level object interface to the Gracenote API.
pygn (pronounced “pigeon”) is a simple Python client for the Gracenote Music Web API, which can retrieve Artist, Album and Track metadata with the most common options.
You will need a Gracenote Client ID to use this module. Please contact developers@gracenote.com to get one.
This module has been enhanced in the following ways beyond the main version, that lives in https://github.com/cweichen/pygn.
Uses the
requests
module for HTTP processing.debug logging is now handled through the
logging
module inDEBUG
mode.extensively fleshed out documentation.
- howdy.music.pygn.createRadio(clientID, userID, artist='', track='', mood='', era='', genre='', popularity=None, similarity=None, count=10, verify=True)
Queries a set of radio stations on Gracenote to create, and returns a
list
ofgnmetadata
dictionaries corresponding to those radio stations that have been created. This was created by the GitHub user Fabian to cover the Gracenote Rhythm API.- Parameters:
artist (str) – the artist name.
track (str) – the song name.
mood (str) – the song mood.
era (str) – the song era.
genre (str) – the genre.
popularity (str) – optional argument. The song popularity.
similarity (str) – optional argument. The song similariy.
count (int) – optional argument, the maximum number of matches to return, must be \(\ge 1\). Default is
10
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- Returns:
a
list
ofgnmetadata
radio stations that match the above query.- Return type:
- Raises:
ValueError – if all of
artist
,track
,mood
,era
, andgenre
are empty.ValueError – if
count
\(\le 0\).
- howdy.music.pygn.fetch(clientID, userID, GNID, verify=True)
Fetches a track or album by their Gracenote API ID.
- Parameters:
- Returns:
a
gnmetadata
containing the metadata for the album.- Return type:
- howdy.music.pygn.get_discography(clientID, userID, artist, rangeStart=1, rangeEnd=10, verify=True)
Queries the Gracenote API service for all albums containing an artist.
- Parameters:
artist (str) – the artist name.
rangeStart (int) – optional argument. This is the order for the HIGHEST cardinal rank of an album that matches a given album name associated with the artist (lower number is better). Must be \(\ge 1\), and default is
1
.rangeEnd (int) – optional argument. This is the order for the LOWEST cardinal rank of an album that matches a given album name associated with the artist (lower number is better). Must be \(\ge 1\), \(ge\)
rangeStart
, and default is10
.verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- Returns:
a
list
of all albums found forartist
. Each album is stored asgnmetadata
.- Return type:
- class howdy.music.pygn.gnmetadata
This class is a dictionary containing metadata fields that are available for the queried item.
- howdy.music.pygn.radioEvent(clientID, userID, radioID, GNID, event='TRACK_PLAYED', count=10, popularity=None, similarity=None, verify=True)
Queries a set of radio stations on Gracenote to find based on certain queries, and returns a
list
ofgnmetadata
dictionaries corresponding to those radio stations that have been found. This was created by the GitHub user Fabian to cover the Gracenote Rhythm API.- Parameters:
event (str) – optional argument, search on what happened to the song whose Gracenote ID is
GNID
. Default isTRACK_PLAYED
.genre (str) – the genre.
count (int) – optional argument, the maximum number of matches to return, must be \(\ge 1\). Default is
10
.popularity (str) – optional argument. The song popularity.
similarity (str) – optional argument. The song similariy.
verify (bool) – optional argument, whether to verify SSL connections. Default is
True
.
- Returns:
a
list
ofgnmetadata
radio stations that match the above query.- Return type:
- Raises:
ValueError – if
count
\(\le 0\).
- howdy.music.pygn.register(clientID, verify=True)
This function registers an application as a user of the Gracenote service.
It takes as a parameter a clientID string in the form of “NNNNNNN-NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN” and returns a userID in a similar format.
As the quota of number of users (installed applications or devices) is typically much lower than the number of queries, best practices are for a given installed application to call this only once, store the UserID in persistent storage (e.g. filesystem), and then use these IDs for all subsequent calls to the service.
- howdy.music.pygn.search(clientID, userID, artist='', album='', track='', toc='', verify=True)
Queries the Gracenote service for a track, album, artist, or TOC entry. TOC is a string of offsets in the format,
150 20512 30837 50912 64107 78357 ...
.- Parameters:
- Returns:
a
gnmetadata
of album metadata corresponding to this query.- Return type:
- Raises:
ValueError – if all of
artist
,album
,track
,toc
, are empty.