Lerne Coding
Wie du mit PHP die Spotify Web API nutzen kannst!
08.03.2021

Spotify eigene, tägliche Playlists mit PHP erstellen

Inhaltsverzeichnis
[[TABLE OF CONTENTS]]
access_timeGeschätzte Lesezeit ca. Minuten

Auf die Idee für dieses Projekt bin ich durch ein persönliches Problem gekommen, was ich mit Spotify habe. Und zwar hat Spotify einen sogenannten "Daily Drive". Das ist eine Playlist, in der sich deine persönliche Musik und zufällige Podcasts abwechseln. In der Regel sind es 4 Lieder, dann 1 Podcast und das wiederholt sich einige male.

Daily Drive in Spotify
Daily Drive in Spotify

Ich persönlich finde die Idee sehr gut, allerdings hat die Umsetzung 2 gravierende Nachteile. Und zwar kann ich nicht selber wählen welche Podcasts ausgewählt werden und ich möchte längere Podcast ausschließen können.

Zuerst hatte ich dem Spotify Support auf Twitter geschrieben. Leider gibt es diese Funktion nicht, sich die Playlists selber anpassen zu können, was mir der Support auch bestätigt hat. Da ich programmieren kann, hatte ich die Idee, mir das einfach selbst nach meinen Vorlieben mit der Spotify API zu programmieren.

Die Funktionalität des Webinterfaces ist bisher noch sehr begrenzt. Es wird eine Verbindung zu Spotify über OAuth 2.0 hergestellt, anschließend geprüft, ob die Playlist für heute schon erstellt wurde. Wenn sie nicht existiert, wird sie erstellt und es wird noch mal angezeigt welche Musik Playlist für die heutigen Daily News verwendet werden.

Daily News - erstellte Playlist in Spotify
Daily News - erstellte Playlist in Spotify

Natürlich kann man das auch anders programmieren, zum Beispiel nach bestimmten Künstlern, Top-Tracks, bestimmte Playlist oder mehrerer Playlists mischen. Da seit ihr nur in euren Programmier-Kenntnissen eingeschränkt, von Spotify kann man eigentlich jede Track-ID bekommen.

Da ich das Rad aber nicht komplett neu erfinden wollte, habe ich auf eine fertige Spotify API Library für PHP zurückgegriffen. Natürlich kannst du die Requests auch selber implementieren, das ist je nach Programmiersprache sicherlich notwendig, wenn noch keine Library vorhanden ist. Aber wenn eine da ist, kann man diese auch verwenden. Bei mir kam die Library jwilsson/spotify-web-api-php zum Einsatz.

Github Logojwilsson/spotify-web-api-php
854 1 158

A PHP wrapper for Spotify's Web API.

Eine Application/Applikation Erstellen

Um nun zu beginnen, diese Anwendung umzusetzen, die ich euch beschrieben habe, müssen wir uns als Erstes in die "for Developers" Oberfläche einloggen, unter dem Menüpunkt "Dashboard" eine Applikation anlegen und diese entsprechend konfigurieren.

Dashboard/Login Spotify: https://developer.spotify.com/dashboard/

Nachdem wir uns eingeloggt haben, können wir eine neue Applikation anlegen. Wir benötigen dort eine App Namen und eine App Beschreibung. Diese werden dem Nutzer später angezeigt, damit dieser auch weiß, welcher Anwendung er seine Nutzerdaten gibt.

Da wir die Applikation nun erstellt haben, landen wir auf der folgenden Oberfläche. Dort müssen wir allerdings noch bestimmte Voreinstellung vornehmen, damit wir uns später auch authentifizieren können.

Application Dashboard
Application Dashboard

Nun können wir die Einstellungen editieren. Dort müssen wir eine Redirect URL festlegen, bei der man nach der erfolgreichen Authentifizierung landen soll. Dort wird dann mit dem Code, der als GET Parameter übergeben wird, weiter gearbeitet.

Spotify Application Einstellungen
Spotify Application Einstellungen

Nun haben wir unsere Anwendung in Spotify erfolgreich angelegt. Wir müssen uns jetzt noch das Client-Secret und die Client-ID kopieren und können mit dem Coding beginnen.

Die Client-ID und -Secret findest du oben rechts auf der Applikations-Übersichts-Seite.

Client-ID & Client-Secret
Client-ID & Client-Secret

Spotify mit PHP verbinden

Um Spotify nun mit PHP zu verbinden, müssen wir als erstes das Composer Paket für die Spotify Web API installieren. Falls du nicht weißt, was Composer ist, empfehle ich dir den Artikel "Composer Paketverwaltung für PHP".

composer require jwilsson/spotify-web-api-php

Nun installiere ich noch "phpdotenv", um mit .env Dateien arbeiten zu können mehr dazu hier. Das ist ein Datei-Format in dem wir Tokens, sensible Daten und Konfigurationen speichern können, ohne dass wir das PHP Skript selbst ändern müssen.

composer require vlucas/phpdotenv

Für unsere Anwendung brauchen wir 3 Parameter in der .env -Datei. Die Client-ID, das Client-Secret und die Login-URL. Das ist die Redirect URL aus den Spotify App Settings.

CLIENT_ID=xxx
CLIENT_SECRET=xxx
LOGIN_URL=http://localhost:9599

Wenn wir das eingerichtet haben, funktioniert unsere Login.php auch schon, wenn wir sie geschrieben haben.

Dazu machen wir jetzt am Anfang die Standard-Einbindungen vom Autoloader für Composer und danach laden wir die Env-Variablen und nutzen diese für die Spotify Session.

Anschließend wird geprüft, ob eine GET-Variable code bereits vorhanden ist. Das ist der Fall, wenn der Spotify Login erfolgreich war. Andernfalls lösen wir den else Case aus, der die URL für die Authentifizierung erstellt und uns dann weiter zur Spotify Seite weiterleitet, wo wir unseren Zugriff bestätigen müssen.

Zustimmung für die Applikation vom Nutzer einholen
Zustimmung für die Applikation vom Nutzer einholen

Wenn der Login dann erfolgreich war, werden wir wieder zu dieser Datei zurückgeleitet und der Refresh und Access Token wird in der Session gespeichert. Anschließend werden wir zur Datei vom eigentlichen Programm weitergeleitet.

require 'vendor/autoload.php';

session_start();

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$session = new SpotifyWebAPI\Session(
    $_ENV['CLIENT_ID'],
    $_ENV['CLIENT_SECRET'],
    $_ENV['LOGIN_URL'] . 'login.php'
);

if (isset($_GET['code'])) {
    $session->requestAccessToken($_GET['code']);

    $_SESSION['refresh'] = $session->getRefreshToken();
    $_SESSION['access'] = $session->getAccessToken();

    header('Location: index.php');
} else {
    $options = [
        'scope' => [
            'ugc-image-upload',
            'user-read-recently-played',
            'user-top-read',
            'user-read-playback-position',
            'user-read-playback-state',
            'user-modify-playback-state',
            'user-read-currently-playing',
            'app-remote-control',
            'streaming',
            'playlist-modify-public',
            'playlist-modify-private',
            'playlist-read-private',
            'playlist-read-collaborative',
            'user-follow-modify',
            'user-follow-read',
            'user-library-modify',
            'user-library-read',
            'user-read-email',
            'user-read-private'
        ],
    ];

    header('Location: ' . $session->getAuthorizeUrl($options));
    die();
}

Im else Fall kannst du noch sogenannte "Scopes" definieren. Das sind Berechtigungen für verschiedene Bereiche der API. So kannst du zum Beispiel extra eine Berechtigung setzen, um die E-Mail des Nutzers lesen zu dürfen, oder um abzufragen, welchen Song der Nutzer grade hört.

Ich habe oben alle Scopes die es gibt aufgelistet. Es ist einfacher, wenn man seine Anwendung programmiert und noch testet, nicht von irgendetwas abhängig zu sein und vollen Zugriff zu haben. Später, in einer produktiv-Umgebung solltest du definitiv den Zugriff so einschränken, dass du nur auf das Zugriff hast, was du definitiv auch von der Spotify Web API benötigst.

Die Playlist automatisch erstellen

Um nun eine Playlist zu erstellen, müssen wir uns in unserer index.php erst wieder mit Spotify verbinden und die Klasse SpotifyWebAPI\SpotifyWebAPI verwenden.

Beachte bei den Beispielen, dass diese auf die Verwendung in einer Klasse ausgelegt sind und nur Ausschnitte aus der fertigen Programmierung am Ende von diesem Artikel zeigen. Dort findest du einen Link zum Github Repository, in dem du immer die aktuelle, komplette Version findest.

$this->session = new SpotifyWebAPI\Session(
    $_ENV['CLIENT_ID'],
    $_ENV['CLIENT_SECRET'],
    $_ENV['LOGIN_URL'] . 'login.php'
);

try {
    $this->session->refreshAccessToken($_SESSION['refresh']);

    $this->api = new SpotifyWebAPI\SpotifyWebAPI();

    $this->api->setAccessToken($_SESSION['access']);

    $this->myPlaylists = $this->api->getMyPlaylists()->items;
} catch (SpotifyWebAPI\SpotifyWebAPIAuthException $th) {
    $this->response = "Dein Login ist abgelaufen.";

    return false;
} catch (SpotifyWebAPI\SpotifyWebAPIException $th) {
    $this->response = "Dein Login ist abgelaufen.";

    return false;
}

Im ersten Schritt prüfen wir den Login. Tritt ein Fehler auf, speichern wir uns die Fehlermeldung. Diese wird später in unserem HTML Template ausgegeben. Ein Redirect zur Login.php wird gesetzt, wenn der Login nicht vorhanden oder nicht korrekt ist.

Um nun die API nutzen zu können, müssen wir den refresh und access Token entsprechend in die Funktion refreshAccessToken und setAccessToken einsetzen. Anschließend können wir uns schon erste Informationen holen.

So kann man sich über die folgende Methode alle meine Playlist als Array holen. Dieses speichern wir uns wie im Beispiel oben auch ab. Diese Abfrage passiert relativ am Anfang, da ich so direkt auch einmal prüfe, ob die Anfragen auch erfolgreich ausgeführt werden können.

$this->api->getMyPlaylists()->items;

Im Anschluss wird mit der Funktion $this->checkPlaylistExists geprüft, ob bereits eine Playlist mit dem Namen existiert, um zu verhindern, dass das Spotify Konto mit unendlich vielen gleichen Playlists gefüllt wird, was natürlich nicht notwendig ist, wenn schon eine Playlist für den Tag existiert.

Anschließend können wir uns die aktuellsten Episoden des gewählten Podcass holen und diese mit der gewählten Musik aus einer zufälligen Playlist kombinieren. Das passiert in der folgenden Methode. myShows enthält eine Liste von Spotify URI's zu unseren Playlisten. Daraus wird nun eine gewählt und bei Bedarf mit weiteren Songs aus einer zweiten Playlist gefüllt. Dieser Fall tritt nur ein, wenn ein Mindestanteil an Songs nicht vorhanden ist. Dieser Wert berechnet sich aus folgender Formel: count($this->myShows) * $this->songCounts, da wir pro Podcast immer 3 Songs brauchen. So brauchen wir zum Beispiel bei 3 Podcast-Episoden und einer Pause von 3 Songs zwischen den Episoden eine Playlist mit 9 Songs.

/**
 * createPlaylistContent
 * Create Array of Podcast and Songs
 * @return array|bool
 */
private function createPlaylistContent(){
    $shows = $this->pullEpisode($this->myShows);
    $songs = $this->getRandomPlaylistTracks($shows);

    $songs = array_chunk($songs,$this->songCounts);
    $chunk = [];

    foreach($songs as $key => $chunk){
        if(isset($shows[$key])):
            $songs[$key][] = $shows[$key];

            $songs[$key] = array_reverse($songs[$key]);
        endif;
    }

    $content = array_chunk(array_unique($this->flatten($songs)),99);

    if(isset($content[0])){
        return $content[0];
    }

    return false;
}

Unser Playlist-Name wird aus dem aktuellen Datum und dem Text "Daily News" generiert. Anschließend, wenn wir den Playlist-Content generiert haben, erstellen wir die Playlist wie folgt:

/**
 * createDailyPlaylist
 *
 * @return string
 */
private function createDailyPlaylist(): string{
    return $this->api->createPlaylist(['name' => $this->playlistName()])->id;
}

Swir diese beiden Funktionen abgerufen haben, können wir die Playlist mit Musik Füllen und ein Bild für die Playlist setzen. Bevor ich allerdings damit Starte Sortiere ich noch einmal die Podcast random. So das ich nicht jeden Tag den gleichen Podcast als Erstes habe. In einem Aufwändigeren Webinterface kann man das alles noch deutlich Detail Verliebter machen mit mehr Optionen für den Ende-Nutzer, um die eigenen Vorlieben besser zu erfüllen.

Um ein Bild per API in der Spotify Playlist zu setzen, musst du dieses Bild Base64 encodiert übertragen. Zusätzlich ist zu beachten, dass dieses nicht größer als 256kb ist und den JPEG Mime-Type besitzt.

shuffle($this->myShows);

if($this->checkPlaylistExists()){
    $playlistContent = $this->createPlaylistContent();
    $playlistID      = $this->createDailyPlaylist();

    if($playlistContent != false){
        $this->api->addPlaylistTracks($playlistID,$playlistContent);

        $this->api->updatePlaylistImage($playlistID,base64_encode(file_get_contents('playlist/' . date('N') . '-news.png')));

        $this->response = "<strong>Erfolgreich</strong> neue Spotify Playlist mit " . count($playlistContent) . " Tracks erstellt."; 
    }else{
        $this->response = "<strong>Fehler</strong> - der Playlist Content konnte nicht generiert werden, versuche es erneut.";
    }

}else{
    $this->response = "Die <strong>Daily News Playlist</strong> existiert bereits für heute.";

    $this->response .= "<span>Unter dem Namen: " . $this->playlistName() . '<span>';
}

Anschließend wird die Antwort über HTML ausgegeben, mit einem entsprechenden Styling das sieht das so aus: Als Erstes rufen wir die Klasse ab und können dann mit $r->getResponse() die Ergebnisse erhalten.

<?php 
$r = new DailyNews();
?>

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Daily News Playlist Creation</title>
    <style>
        *{
            font-family: "Lato","Roboto",sans-serif;
            font-size: 19px;
        }    

        body{
            display: flex;
            justify-content: center;
            align-items: center;
            align-content: center;
            height: 100vh;
            background: #121212;
            color: #fff;
        }

        body .response{
            display: flex;
            justify-content: center;
            align-items: center;
            align-content: center;
            flex-direction: column;
            background: #181818;
            padding: 40px;
            border-radius: 6px;
            text-align: center;
        }

        body .response img{
            border-radius: 6px;
        }

        body .response div{
            margin-top: 40px;
        }

        body .response a{
            padding: 15px 45px;
            margin-top: 15px;
            background: pink;
            text-decoration: none;
            background: #1db954;
            color: #fff;
            border-radius: 50px;
        }

        strong{
            color: #1db954;
        }

        span{
            display: block;
            font-size: 16px;
            color: #656565;
            padding-top: 5px;
        }
    </style>
</head>
<body>
    <div class="response">
        <img src="playlist/<?php echo date('N') ?>-news.png">
        <div><?php echo $r->response(); ?>
            <?php if(!empty($r->playlistName)): ?>
                <span>Musik für Daily News heute: <?php echo $r->playlistName; ?></span>
            <?php endif; ?>
        </div>
        <?php if($r->go == false){ ?>
            <a href="/login.php">Spotify verbinden</a>
        <?php } ?>
    </div>
</body>
</html>

Wie könntest du jetzt weiter machen?

Natürlich kannst du mit der Spotify Web API noch deutlich mehr steuern und auch die Möglichkeiten des Webinterfaces deutlich erweitern.

Hier ein paar Ideen was du noch dazu programmieren könntest:

  • Ein Interface, um die Podcasts auszuwählen, die für die Generierung genutzt werden sollen, basierend auf deinen Podcast die du abonniert hast.
  • Eine Option die Zeit zu konfigurieren, wie lang oder kurz eine Episode sein muss, um in die Playlist für den Tag zu kommen.
  • Eine Möglichkeit die Musik selber auszuwählen oder bestimmte Playlists vorauszuwählen um die Musik genauer eingrenzen zu können anstatt nur zufällig aus deinen Playlists, denen du folgst, wählen zu können.
  • Oder man speichert die Credentials in einer Datenbank oder Datei und kann sich dann einen Cronjob einrichten, der die Playlist jeden morgen um 8 Uhr automatisch für einen erstellt. Diese Möglichkeit habe ich für mich nicht umgesetzt, da ich mich bewusst dafür entscheiden will, da ich sonst ziemlich schnell mein Spotify voller Daily News Playlists habe.
  • Alternativ kannst du auch eine Playlist täglich updaten. So brauchst du nicht jeden Tag eine neue Playlist erstellen und es werden nur die Songs und Podcast Episoden in der Playlist getauscht.

Fazit

Ich hoffe, du hast hier einige Ideen aufgreifen können, wie du mit der Spotify Web API arbeiten kannst.

Als weiterführende Links kann ich dir die folgenden beide Ressourcen empfehlen: Einmal die offizielle Dokumentation von Spotify, falls du es in einer anderen Programmiersprache umsetzen willst.

Spotify API Dokumentation: https://developer.spotify.com/documentation/web-api/

Und einmal die offizielle Dokumentation des PHP Composer Moduls.

Diese findest du unter dem folgenden Link: https://github.com/jwilsson/spotify-web-api-php/tree/main/docs

Nun noch zum Stöbern der Link zum Repository, in dem du den gesamten Code von diesem Artikel zur Spotify Web API findest.

Github Logofschuermeyer/spotify-daily-news
2 0 0

Create a Daily News Playlist

Ich persönlich nutze die Daily News, die ich mir nun selber erstellen kann seit einigen Tagen und diese gefallen mir deutlich besser als der Daily Drive.

Viel Spaß beim Experimentieren mit der Spotify API.

Bildquelle - Vielen Dank an die Ersteller:innen für dieses Bild
Kommentare zum Artikel

Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "Wie du mit PHP die Spotify Web API nutzen kannst!"!

Kommentar schreiben

Vom Autor Empfohlen
close