A Python-based application that interacts with the Spotify API to manage playlists. The contained scripts act as an abstraction-layer to the API itself to allow for easier playlist management.
Important
The functionality in OSinterface.py
assumes that the songs in the local directory are named after the following pattern:
artist - songname.mp3
Count all songs per artist in a local directory and return a dictionary:
artist_song_map = OSinterface.get_artist_song_map(myLocalPlaylistPath, sort_alphabetically=True)
print(artist_song_map)
Collect all locally stored songs and return a generator of artist-song tuples:
artist_song_tuples = OSinterface.get_artist_song_tuples(myLocalPlaylistPath, sort_alphabetically=True, case_sensitive=False, ignore_brackets=True)
Add all songs to the playlist using the parallel method to avoid rate limiting (that could otherwise occur when using the sequential method):
The method will first loop through the provided generator of artist-song tuples and search for the track on Spotify. The returned track ID will be stashed in a list and added if the maximum batch size of 100 is reached, or an exception is raised.[!TIP] Should the API fail to find the searched track, all currently cached tracks will be added, and execution will pause until confirmation is provided via the console. This is to allow for manually adding the missing track to maintain the playlist order
# `artist_song_tuples` is defined in the "Collect All Locally Stored Songs" section
succeeded, failed = add_parallel(artist_song_tuples)
Optionally, log the changes made to the playlist:
# `succeeded` and `failed` are defined in the "Add All Songs to the Playlist" section
spotifyClient.log_playlist_changes(myPlaylistURI, description=f'Added {len(succeeded) - len(failed)} items on {datetime.datetime.now().strftime("%Y-%m-%d")}')
Read all songs from the playlist and parse the response:
response = spotifyClient.get_all_playlist_tracks(myPlaylistURI, fields="items(track(name,artists(name))")
playlistContent = spotifyClient.parse_artist_song(response)
for artists, song in playlistContent:
if len(artists) > 1:
print(f"{' & '.join(artists)} - {song}")
else:
print(f"{artists[0]} - {song}")
Count and print duplicate songs in the playlist:
# `playlistContent` is defined in the "Read All Songs from the Playlist" section
cleaned = playlistContent
song_counts = {song: cleaned.count(song) for song in cleaned}
duplicates = {song: count for song, count in song_counts.items() if count > 1}
for song, count in duplicates.items():
print(f"{song} \t\t {count}")
Add the most listened songs to the top of the playlist:
add_parallel(OSinterface.read_most_listened_file(myPlayTimePath, lines=25), position=0)
spotifyClient.log_playlist_changes(myPlaylistURI, description=f'Added the 25 most listened tracks to the top of the playlist')
Note
The read_most_listened_file
function reads the first lines of a plain-text file with path myPlayTimePath
that contains the songs, in my case sorted by descending play count.
This file is generated by an external software. The expected format is artist - songname
, brackets of any kind are ignored.
- Python 3.x
spotipy
librarydotenv
library- Spotify Developer Account
-
Clone the repository:
git clone https://github.com/grn-x/Python-Playlist-Digitization.git cd spotify-playlist-manager
-
Install the required Python packages:
pip install -r requirements.txt
-
Set up your Spotify API credentials in the
source/credentials.env
file:SPOTIPY_CLIENT_ID='your_client_id' SPOTIPY_CLIENT_SECRET='your_client_secret' SPOTIPY_REDIRECT_URI='http://127.0.0.1:9090'
Note
To obtain your Spotify API credentials, create a new application on the Spotify Developer Dashboard. Refer to the Spotify web-API docs for more information.
- Run the
main.py
script or use isolated features in your own scripts:python main.py
The main.py
script contains usage examples for the different features of the application. Run the script to see the examples:
- Add Tracks by their OS filename
- Search for duplicates
- Handle track not found exceptions
- Add option to auto skip missing tracks
- Implement Metadata Extraction
- chain to ID3v2 tagging
If you have any questions or suggestions, feel free to open an issue or a pull request.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.