Idee

Der Musik-Algorithmus generiert den Musikmix für den Sender und schaut dabei, welche Songs gerade angesagt sind. Dazu werden jede Woche Daten von YouTube und anderen Plattformen analysiert. Auch Wetterdaten fließen in die Berechnung mit ein. Das Projekt ist noch in Entwicklung, den Quellcode gibts wie immer hier auf GitHub. Wer mal reinhören möchte, findet den Sender direkt über Alexa (“Alexa, spiele Radio J F M“) oder unter radiojfm.de

Der “Playlist-Generator” wurde mit dem Ziel entwickelt einen komplett autonomen Radiosender zu erfinden, der sich durch genaues Erkennen von Trends von anderen Sendern abhebt oder zumindest vergleichbar gutes Programm liefert. Grundlage dabei sind spezifische Metadaten von Anbietern wie YouTube oder Spotify, die für jeden einzelnen Song wöchentlich erhoben werden. Hinzu kommen für jede Stunde aktuelle Wetterdaten. Ausschlaggebend für ein abwechslungsreiches Programm ist die Analyse der bereits gespielten Song, sodass keine Dopplungen Stattfinden oder Songs zu häufig gespielt werden.

Neben der Auswahl der Songs, werden aber auch Nachrichten und Jingles eingefügt, und an die “Ramp” des Songs angepasst. Zusätzlich gibt es am Ende jeder Stunde eine kurze Übersicht, welche Songs in der nächsten Stunde laufen. Hier werden die “Hooks” von drei zufälligen Songs der nächsten Stunde gespielt.

Ramp

Eine Ramp ist die Zeitspanne zu Beginn des Songs, in der noch kein Gesang zu hören ist. Meist sind das ca. 5-20 Sekunden. Beim Liveprogramm sieht der Moderator, wie lange er noch reden kann, wie viele Sekunden es also noch bis zur Ramp sind. Aber auch in der Radio-Automation kann man z.B. Jingles auf eine Ramp setzen. Ein Beispiel findet ihr unten im Post.

Hook

Eine Hook beschreibt einfach gesagt die markanteste Stelle eines Songs, also die Stelle, an der die meisten Leute den Song erkennen würden. Beim Importieren eines Songs wird die Hook automatisch ermittelt und in der Datenbank gespeichert. Die automatisch generierte Hook für “Bad Habits” klingt z.B. so:

Metadaten

Spotify

Die Daten von Spotify kommen aus der Spotify API, die kostenlos verfügbar ist. Hier können neben gewöhnlichen Metadaten, wie Name des Albums, oder Künstlernamen, auch Analysen abgefragt werden. Mit den Analysen von Spotify kann bestimmt werden, wie sich ein Song anhört und wirkt. Diese Informationen werden dazu verwendet, um z.B. nicht mehrere akustische Songs hintereinander zu spielen oder “fröhliche” und “traurige” Songs abwechselnd zu spielen. Ein Beispiel für eine Antwort aus der Spotify API:

{
  "acousticness": 0.00242,
  "analysis_url": "https://api.spotify.com/v1/audio-analysis/2takcwOaAZWiXQijPHIx7B",
  "danceability": 0.585,
  "duration_ms": 237040,
  "energy": 0.842,
  "id": "2takcwOaAZWiXQijPHIx7B",
  "instrumentalness": 0.00686,
  "key": 9,
  "liveness": 0.0866,
  "loudness": -5.883,
  "mode": 0,
  "speechiness": 0.0556,
  "tempo": 118.211,
  "time_signature": 4,
  "track_href": "https://api.spotify.com/v1/tracks/2takcwOaAZWiXQijPHIx7B",
  "type": "audio_features",
  "uri": "spotify:track:2takcwOaAZWiXQijPHIx7B",
  "valence": 0.428
}

Wichtig für den Algorithmus ist vor allem der “energy”-Wert, welcher die Intensität und Aktivität eines Songs misst. Songs mit einem hohen Wert sind meistens schnell und laut, wie z.B. Death Metal. Wohingegen Songs mit einem niedrigen Wert leiser und ruhiger sind. Der “valence”-Wert fließt im Sommer mit in die Generierung ein. Der Wert beschreibt wie “fröhlich” ein Song ist, und im Sommer sollen tendenziell eher fröhliche Songs gespielt werden.

YouTube

Um Trends zu erkennen werden wöchentlich für alle Songs aus der Datenbank die Views, Likes und Dislikes der dazugehörigen YouTube Videos abgefragt und gespeichert. Die Trends werden dann durch folgende Formel bestimmt:

p = (b-a)/t

Mit dieser Formel erhält man den prozentualen Anteil, der neuen Views dieser Woche, vom der Gesamtanzahl an Views des Videos. Das heißt soviel wie: “Wie viele Aufrufe hat das Video in dieser Woche bekommen, und wie viele sind das im Vergleich zur Gesamtanzahl an Aufrufen?”. Hierzu wird zunächst ausgerechnet, wie häufig das Video in dieser Woche aufgerufen wurde (b-a). Dieser Wert wird dann in Relation zu der Gesamtanzahl an Views gesetzt, da 500 von 1000 Aufrufen innerhalb von einer Woche natürlich eine ganz andere Bedeutung haben als 500 von 1 Millionen. Je höher dieser Wert also ist, desto “stärker” ist der Trend. Das gleiche wird auch mit den Likes und Dislikes gemacht, um zu erkennen, ob es sich um einen positiven oder negativen Trend handelt und wie stark ein Video bewertet wird.

Punkte

Für jeden Song werden “Punkte” berechnet. Durch die Vergabe von Punkten werden Songs, die bestimmte Kriterien eher erfüllen, häufiger gespielt bzw. wahrscheinlicher ausgewählt. Die Punkte werden für jede Stunde neu berechnet.

Die Berechnung erfolgt unter anderem mit den Daten von YouTube (Trends). Ist ein Song auf YouTube besonders beliebt, so erhält dieser mehr Punkte. Wird ein Song jedoch besonders schlecht auf YouTube bewertet, werden allerdings auch Punkte abgezogen. Mit einberechnet wird die Song-Historie, also den zuletzt gespielten Songs. Wenn ein Song in den letzten Tagen häufiger gespielt wurde, bekommt dieser auch weniger Punkte, anders herum natürlich genauso. Für das Alter des Songs gibt es je nach dem auch extra Punkte oder Abzüge. Hier unterscheidet das Programm aber auch zwischen Oldies und neuen Songs, da Oldies für ihr Alter selbstverständlich keine Punkte abgezogen bekommen. Im Sommer berechnet der Algorithmus für Songs mit einem hohen “valence”-Wert ebenfalls mehr Punkte.

Generieren einer Playlist

Die Playlisten für den nächsten Tag werden jeden Abend um 22 Uhr generiert. Eine Playlist ist je eine Stunde lang. Zunächst wird eine sog. “emergency playlist” erstellt, die abgespielt werden kann falls eine generierte Playlist zu kurz sein sollte, was jedoch nur sehr selten passiert.

Nach der Notfall Playlist wird für jede Stunde eine eigene Playlist generiert. Zu Beginn wird ermittelt, welche Jingles in dieser Stunde gespielt werden können. Die Jingles unterscheiden sich zum einen in Tages- und Jahreszeit aber auch in “Stimmung”, also eher ruhige Jingles für ruhige Songs. Außerdem gibt es spezifische Jingles für Wochenenden.

Danach werden alle Songs zusammengesucht, die in der bestimmten Stunde gespielt werden können. Ob ein Song in einer Stunde gespielt werden kann, kommt auf den Radiosender an. Bei dem einen Sender laufen z.B. nachts DJ Songs und bei einem anderen Mozart. Diese Auswahl wird für jeden Song beim Import in die Datenbank mit angegeben. Für jeden Song werden Punkte vergeben. Je mehr Punkte ein Song hat, desto beliebter ist dieser gerade (Siehe “Punkte”). Mit dem folgendem Abschnitt erhält man die spielbaren Songs als Playlist-Objekt, wobei “date” ein Objekt vom Typ datetime sein muss:

sourcePlaylist = db.getAvailablePlaylistItems(date)

Nun wird aus den verfügbaren Songs jeweils der “beste” ausgewählt und der Playlist hinzugefügt.

playable = sourcePlaylist.filterPlayableTracks(playlist.getItems())

Die Funktion “filterPlayableTracks” gibt eine Playlist mit allen Songs zurück, die auf Grundlage der bereits ausgewählten Songs spielbar wären. Hierbei wird z.B. der “energy”-Wert des letzten Songs betrachtet. Ist dieser unter einem bestimmten Wert, so werden nur Songs mit einem vergleichsweise hohem Wert zurückgegeben. Beim dem Alter des Songs funktioniert es genau so, wurde zuletzt ein älterer Song gespielt, so werden nur neue Songs zurückgegeben. Werden keine Songs mit diesen Werten gefunden, dann werden die Suchfilter ausgesetzt und somit auch Song zurückgegeben, die den Anforderungen nicht entsprechen, da die Playlist sonst nicht die nötige Länge erreichen würde.

Aus der Liste der spielbaren Songs wird nun zufällig entweder der mit den meisten Punkten, oder ein zufälliger ausgewählt. Somit bleiben am Ende der Stunde auch noch gute Songs (mit vielen Punkten) verfügbar. Anschließend wird überprüft, ob der Künstler des ausgewählten Songs auch in einem der letzten drei Songs wieder zu finden ist. Falls nicht, kann der Song verwendet werden. Dies stellt sicher, dass die Vorgaben der GEMA eingehalten werden. Der ausgewählte Song wird nun zur Playlist für die aktuelle Stunde hinzugefügt und aus der “sourcePlaylist” gelöscht, sodass er in dieser Stunde nicht nochmal gespielt werden kann.

Für die Vorschau zum Ende jeder Stunde werden nun drei Songs aus der generierten Playlist ausgewählt, die in der Stunde zuvor angekündigt werden sollen. Hierfür wird dann eine kurze MP3 erstellt, die eine Moderation und die jeweilige Hook der Songs, beinhaltet.

Im nächsten Schritt werden der Playlist Jingles hinzugefügt, und wenn möglich auf die Ramp des Songs gelegt. Die Ramp wird beim Import berechnet, indem Gesang und Instrumental voneinander getrennt werden. Der Einsatz des Gesangs kann somit durch eine Stille-Erkennung ermittelt werden. Falls ein Song neu ist (Nicht älter als 60 Tage) wird automatisch ein Promo-Element erzeugt, um den neuen Song anzukündigen und als neu zu präsentieren. In Kombination mit der Ramp hört sich ein automatisch generiertes Promo-Element so an:

Zum Schluss wird die Playlist als JSON-Datei exportiert, und zu beginn der generierten Stunde von mAirList gelesen und abgespielt.

Wenn Dich der Post interessiert hat, schau Dir gerne noch weitere Projekte oder meinen Blog an!

Quellen

https://developer.spotify.com/documentation/web-api/reference/#/operations/get-audio-features