Spotify en Google Play Music aansturen met scripts

Redactie
0

spotify_scripten

Zowel Google Play Music als Spotify zijn aan te sturen met zelfgeschreven software. We laten als voorbeeld zien hoe je met een klein Python-script je playlists van Google overzet naar Spotify.

Streamingdiensten wekken de indruk gesloten werelden te zijn. Heb je bijvoorbeeld bij Spotify of een andere muziekdienst al wel eens een functie gezien om playlists te exporteren? Tuurlijk niet! Als je dat zou kunnen, zou je ook makkelijk naar een andere aanbieder kunnen overstappen. Spotify biedt gelukkig wel een web-API waarmee je vrijwel alle functies van de streamingdienst kunt aansturen – inclusief het afspelen van willekeurige nummers en het opstellen en uitlezen van afspeellijsten. De volgende url zoekt via de web-API naar een klassieker uit de punkmuziek. Dat werkt zowel in de browser als met bijvoorbeeld curl:

https://api.spotify.com/v1/search?q=clash+london+calling&type=track

Vervolgens krijg je een JSON-lijst met resultaten. London Calling staat namelijk in diverse uitvoeringen op meerdere albums.

Spotify heeft zelfs een interactieve Web API Console die je helpt de url goed te formuleren.

De interactieve console is handig om de web-API van Spotify te leren begrijpen.

De interactieve console is handig om de web-API van Spotify te leren begrijpen.

Als je iets anders wilt maken dan een webapplicatie met JavaScript, zijn url’s en JSON-structuren voor eigen applicaties eigenlijk niet erg handig. Daarom biedt Spotify naast de web-API ook een SDK voor Android en iOS en een C-bibliotheek. Paul Lamere heeft bovendien de Python-bibliotheek Spotipy geschreven die de aanroepen van de web-API omzet in handige Python-objecten, -functies en -datastructuren.

Wie ben ik?

Bij Google is het wat minder duidelijk. Er bestaat geen officiële API voor Play Music. Gelukkig heeft Simon Weber zich daar al eerder over gebogen en zijn inzichten verwerkt in de Python-bibliotheek Gmusicapi. Net als Spotipy installeer je die bibliotheek met pip3. Gmusicapi heeft verschillende interfaces, waarvan Mobileclient de eenvoudigste is. Voor de authenticatie heb je genoeg aan de gebruikersnaam van Google (USER), het wachtwoord (PASS) en een 16-cijferig hexadecimaal getal als pseudo-device-id:

from gmusicapi import Mobileclient

gm = Mobileclient()

if not gm.login(USER, PASS, '0123456789abcdef'):

print('login for', USER, 'failed')

Als je two-factor-authenticatie  gebruikt, moet je eerst een specifiek wachtwoord aanmaken voor de app en dat gebruiken.

Authentificatie bij Spotify

Bij Spotify is het wat ingewikkelder om je aan te melden. Naast de feitelijke client library zit in de bibliotheek van Spotipy nog een Util-module. Bij de listing hieronder zie je hoe authenticatie werkt. Geef als username je gebruikersnaam van Spotify op. Nadat je je applicatie bij Spotify geregistreerd hebt, krijg je de waarden voor client_id en client_ secret geleverd.

spotify_authenticatie

Bij Spotify kost authenticatie wat meer moeite dan bij Google Music.

Met de parameter scope wordt ingesteld welke rechten de applicatie nodig heeft, bijvoorbeeld het lezen en aanpassen van de muziekbibliotheek of het uitlezen van informatie via de gebruiker. Ons voorbeeldscript wil alleen nieuwe playlists aanmaken, zodat je genoeg hebt aan de rechten om eigen en openbare playlists te wijzigen.

Als het script de eerste keer wordt gestart, probeert util.prompt_for_user_token een Spotify-url in de browser op te roepen. Het daarvoor gebruikte programma open is echter alleen beschikbaar bij OS X. Bij Linux moet je de url van Spotify die je in de command line ziet, zelf in de browser plakken. Nadat je het script daar toegang gegeven hebt, krijgt de browser de bijbehorende redirect_uri, aangevuld met een autorisatiecode. Kopieer die url met de code als antwoord naar de terminal van het script om toegang door het script mogelijk te maken. Een webapplicatie zou daar natuurlijk de url van een eigen callback-functie neerzetten die de autorisatie afhandelt.

Hier met die nummers!

Bij Google Music is het uitlezen van de playlists redelijk triviaal:

playlists = gm.get_all_user_playlist_contents()

toont een overzicht met allerlei informatie over alle afspeellijsten. Om de inhoud te analyseren, kun je het beste met de JSON-module zorgen voor een weergave met een overzichtelijke opmaak:

import json

...

for pl in playlists:

  print(pl['name'])

  print(json.dumps(pl, indent=4))

In de playlists is met name de lijst tracks belangrijk. Die heeft een record voor elk nummer op de afspeellijst met alle relevante informatie:

for tr in pl['tracks']:

  try:

    title = tr['track']['title']

artist = tr['track']['artist'] except: continue

We hebben het zoeken naar de titel en de artiest een voorkeursbehandeling gegeven door ze apart te zetten. Sommige playlists bevatten namelijk wel eens tracks zonder specifieke informatie. Ons script voegt bij dergelijke nummers de ‘trackId’ aan de lijst missing toe, waarop de niet naar Spotify meegenomen nummers komen te staan.

Filteren

Met title en artist kun je dan op Spotify naar het nummer zoeken:

hits = sp.search(artist+' '+title, limit=50, offset=0, type='track')

n = hits['tracks']['total']

De zoekfunctie levert een zogeheten dictionary terug. Het item tracks in total levert daarbij het aantal resultaten. Op de lijst items staan de gevonden nummers. Spotify zoekt overigens zeer breed: als je zoekt naar ‘Clash London Calling’ krijg je onder meer alle nummers van het album ‘London Calling’ te zien.

De filterfunctie filter_hits() ruimt de lijst van gevonden nummers in hits[‘tracks’][‘items’] daarom op. Alle resultaten waarbij de artiest of het nummer niet overeenkomen met de gezochte artiest en het nummer worden daarbij weggegooid (zie de listing hierboven). Pas op: het veld ‘artist’ bevat een lijst artiesten die allemaal moeten worden gecontroleerd. Om werk te besparen wegens subtiele verschillen in de schrijfwijze van Google Music en Spotify, zet het script de strings voor het testen in kleine letters.

Een filterfunctie ruimt de lijst met resultaten op.

Een filterfunctie ruimt de lijst met resultaten op.

Nog meer?

Een ander probleem: Googles ‘London Calling (Remastered)’ heet bij Spotify ‘London Calling – Remastered’. Vandaar dat het script alleen vergelijkt tot het eerste haakje in de naam bij Google. De functie levert een lijst met de resterende ‘goede’ resultaten. De overige informatie in hits is niet meer nodig:

items = filter_hits(hits)

Een eerste aanroep van de zoekfunctie hoeft niet meteen alle resultaten op te leveren. Als limit stel je het aantal treffers in dat per oproep maximaal geleverd moet worden – standaard is dat tien. Bij honderd werkt Spotify niet meer mee, vandaar dat het script er vijftig gebruikt. Mocht het aantal resultaten de limit overschrijden, dan moet je de zoekfunctie meerdere keren aanroepen en de offset daarbij aanpassen:

search = 1

while search*50 < n:

hits = sp.search(artist+' '+title, limit=50, offset=search*50, type='track')

search += 1

items += filter_hits(hits)

Omdat de filterfunctie simpelweg een lijst met nummers oplevert, kun je het resultaat van elke volgende zoekopdracht gewoon aan de lijst toevoegen. Meerdere varianten van het gezochte nummer blijven in eerste instantie op de lijst met resultaten staan.

Naar Spotify

Dan ontbreekt op Spotify alleen nog de nieuwe afspeellijst die met Spotipy gemaakt is (zie listing). Bij het toevoegen van nieuwe nummers wordt de lijst later via de id aangesproken.

Een nieuwe playlist op Spotify kun je snel aanmaken.

Een nieuwe playlist op Spotify kun je snel aanmaken.

Daarnaast heb je de track-id van het beste resultaat uit de lijst items nodig. Maar welke is de beste? We hebben het makkelijk gemaakt: Spotify kent aan elk nummer een populariteitswaarde toe tussen 0 en 100 – we nemen gewoon het nummer met de hoogste populariteit.

De functie in Spotipy voor het toevoegen van nummers aan een playlist gaat uit van een lijst met de track-id’s van Spotify. De id van het populairste nummer moet dus in een lijst worden doorgegeven. Als Spotify geen resultaat heeft opgeleverd, voegt het script de artiest en de titel toe aan de reeds genoemde missing-lijst.

pop = 0

spotify_id = ''

for track in items:

if track['popularity'] >= pop:

spotify_id = track['id']

pop = track['popularity']

res = sp.user_playlist_add_tracks( USERNAME, spotify_playlist_id, [spotify_id])

Nadat de playlist is afgewerkt, laat het script ter controle de lijst missing zien met de nummers die niet zijn overgezet. Als daar te veel nummers in staan, kun je met de diagnostische informatie van het script controleren wat er eventueel verkeerd is gegaan. Het percentage nummers dat op Spotify niet werd gevonden of waarbij Google de titel en de artiest niet leverde, lag in onze test onder de tien procent.

Playlists converteren

We hebben een Python 3-script gemaakt dat de playlists van Google Music overzet naar Spotify. Voordat je dat de eerste keer start, moet je aan het begin van het script je eigen inloggegevens opgeven (USER, PASS, USERNAME). Vergeet ook niet de Python-bibliotheken gmusicapi en spotipy te installeren met pip3 (pip3 install gmusicapi respectievelijk pip3 install spotipy). Kun je niet inloggen bij Spotify, registreer het script dan onder je eigen Spotify-account zoals hierboven beschreven. Gebruik daarbij de gegenereerde Client_ID.

(Oliver Diedrich / Marcel van der Meer)

Deel dit artikel

Lees ook

Energie meten met Raspberry Pi: snel en overzichtelijk je verbruik zien

Wanneer je thuis een slimme meter hebt geïnstalleerd, kun je je energie meten met Raspberry Pi. Energieverbruik is in te zien via gratis te downloaden...

Donkere modus Word uitschakelen of inschakelen? Zo simpel doe je het!

Microsoft Word volgt automatisch de donkere modus van Windows. Je kunt ook afzonderlijk de donkere modus van Word uitschakelen of inschakelen. Zo doe ...

0 Praat mee
avatar
  Abonneer  
Laat het mij weten wanneer er