Lokale Musik: Spotifys Radio reimplementieren
Radio auf Grundlage meiner Vorlieben, MusicBrainz und YouTube Music
Das Radio: Spotifys und YouTubes Tuning-Achsen, lokal nachgebaut#
Spotifys Radio-Funktion ist ein Hit-oder-Miss-Feature: Entweder erzeugt es eine unbrauchbare Playlist mit viel irrelevanten Songs, oder trifft den Wunsch zufällig perfekt und dann hängt man ewig in der Playlist fest. Bei der rein lokalen Musik-Bibliothek muss die Radio-Funktion nachgebaut werden. Dazu musste ich verstehen, was Spotify und YouTube Music eigentlich tun, wenn sie „ein Radio machen” und es anschließend reimplementieren.
Wie Spotify das Radio baut#
Spotifys Empfehlungen ruhen laut Recherche auf drei Säulen: Collaborative Filtering (ein Audience-Overlap-Graph nach dem Muster „wer A hört, hört auch B”), Audio-Feature-Analyse (Tempo, Energy, Danceability, Valence einzelner Tracks) und NLP (kulturelle Schlagworte, die aus dem Web über einen Künstler gesammelt werden).
Sichtbar gemacht wird das über zwei Achsen als Chip-Leiste. Die erste ist der Personalisierungs-Grad: Personalised ↔ (Default) ↔ More discovery. Im Personalised-Tab tauchen deutlich mehr Tracks mit grünem Haken auf (geliked oder in der eigenen Library) und mehr Songs des Seed-Künstlers selbst; More discovery schiebt unbekanntere Acts nach vorn. Im Kern ist dieser Regler ein Gewicht zwischen dem Geschmacksvektor des Hörers und der reinen Ähnlichkeit zum Seed. Die zweite Achse ist ein Genre-Constraint: Non-personalised · Pop Punk · Pop Rock · Rock. Diese Chips werden aus den Genres des Seed-Künstlers abgeleitet, ein Klick schränkt den Pool auf diese Genre-Nachbarschaft ein.

Die ersten rund fünf Tracks eines Radios sind immer die neuesten Releases aus dem Umfeld des Seeds. Über mehrere Künstler hinweg geprüft und jedes Mal gleich: „Against The Current Radio” startet mit Dead Man Walking (der ATC-Single vom 22. Mai 2026), „Gracie Abrams Radio” mit Hit the Wall, „Olivia Rodrigo Radio” mit the cure, jeweils das jüngste Single, und die Künstler stehen gegenseitig in den Top 3. Erst danach folgt der popularitäts- und vertrautheitsbasierte Rest.
Wie YouTube Music das Radio baut#
YouTube Music macht dasselbe Tuning explizit über Chips. Beim Anlegen einer Station wählt man zusätzlich bis zu 30 Seed-Künstler, eine Artist-Variety (low/medium/high) und eine Song-Selection (Familiar/Blend/Discover); dazu kommen Filter-Chips wie Popular, Deep cuts, New releases, Pump-up, Chill und Focus. Über der laufenden Station steht die Leiste All · Familiar · Popular · Discover · Deep cuts · 2010s · Pump-up, jeder Tab ist eine andere Stellung derselben Maschine.

Die Tabs zerlegt, am Beispiel des Seeds Against the Current:
| Tab | Charakter | Belege aus dem Tab |
|---|---|---|
| All | ausgewogene Default-Mischung: einige Seed-Tracks vorn, dann Collabs und enge Genre-Nachbarn | weapon (ATC), Catch My Breath (Alex Goot & ATC), Legends Never Die (LoL & ATC), Teenagers (Summer Set & ATC), Not A Love Song (Pale Waves), Too Much (Crashing Atlas) |
| Familiar | breit bekannte Mainstream-Songs, große Namen | Demons (Imagine Dragons), Welcome to the Black Parade (MCR), Numb (Linkin Park), 7 Years (Lukas Graham), Shatter Me (Lindsey Stirling) |
| Popular | global meistgehörte Tracks der Nachbarschaft | Rumors (NEFFEX), Heart Attack Rock Version (Demi Lovato), Heroes Are Calling (Smash Into Pieces), Devils Don’t Fly (Natalia Kills) |
| Discover | wenig bekannte Tracks und Künstler, tiefere Nachbarn | Airhead (Honey Revenge), The One (Dela Kay), ONE OK ROCK-Cover (ATC Fans), Loner (Maggie Lindemann) |
| Deep cuts | Album-Tracks, Akustik- und Cover-Versionen, B-Seiten | Something You Need (ATC, tiefer Albumtrack), Talk (Acoustic) (ATC), She Looks So Perfect (5SOS-Cover durch ATC), Good 4 U (Cover) |
Daraus ergeben sich vier orthogonale Achsen, die einzeln gedreht werden: Seed-Konzentration (wie viele Seed-eigene Tracks gegenüber Nachbarn), Popularität (Popular gegenüber Deep cuts, gemeint ist der globale Bekanntheitsgrad eines Tracks), Vertrautheit (Familiar gegenüber Discover, also wie mainstream ein Künstler ist) und Era oder Mood als Zusatzfilter (2010s, Pump-up, Chill).
Popular und Familiar sind dabei nicht dasselbe: Popular zieht die spielzahlstärksten Tracks der konkreten Nachbarschaft, Familiar die kanonischen großen Hits (MCR, Linkin Park), die fast jeder kennt, auch wenn sie stilistisch weiter weg liegen.
Beide reduzieren auf dieselben Achsen#
Stellt man Spotify und YouTube Music nebeneinander, beschreiben sie dieselbe Mechanik mit unterschiedlichen Worten:
| Achse | Spotify | YouTube Music |
|---|---|---|
| Ähnlichkeit (Künstler-Universum) | CF-Audience-Graph | Seed-Künstler-Stationen |
| Seed-Konzentration / Variety | implizit ~40 % Seed | Artist-Variety low/med/high |
| Popularität | implizit | Popular ↔ Deep cuts |
| Vertrautheit / Personalisierung | Personalised ↔ More discovery | Familiar ↔ Discover |
| Genre-Constraint | Genre-Chips | Genre- / Mood-Filter |
| Era | implizit | Dekaden-Chip (2010s) |
| Mood / Energy | Audio-Features | Pump-up / Chill / Focus |
| Recency | aktuelle Releases in den Top 5 | New-releases-Filter |
Es gibt nicht fünf verschiedene Radio-Algorithmen, sondern eine Engine und einen Satz orthogonaler Tuning-Achsen. Ein Artist-Radio, ein Album-Radio, ein Genre- oder Era-Radio unterscheiden sich nur darin, wie das Anfangs-Universum gebildet wird, der Rest der Pipeline ist identisch.
Worauf die Achsen lokal aufsetzen#
Jede dieser Achsen braucht eine lokale Datengrundlage. Die drei externen Quellen, die mir ohne Spotify zur Verfügung stehen, decken sie unterschiedlich gut ab: Last.fm (Hörhistorie, ähnliche Künstler, Tags, globale Popularität, Loved Tracks), MusicBrainz (Band-Mitglieder, Genres, Release-Daten) und YouTube Music über yt-dlp (Auflösung nicht-besessener Tracks zu abspielbaren URLs, plus ein eigener related-Graph). Dazu drei lokale Bausteine: Die beets-Bibliothek als Universum der vorhandenen FLACs, die Künstler-Rangliste interesting_artists.json als Personalisierungs-Signal und die kuratierten playlist_data-Playlists.
Was radio.py an Quellen einbindet und was herauskommt:
flowchart LR
LFM["Last.fm<br/>Similars · Top-Tracks<br/>Tags · Loved"]
MB["MusicBrainz<br/>Mitglieder · Release-Daten"]
YTM["YouTube Music<br/>related-Graph · yt-dlp-Auflösung"]
BEETS["beets-Bibliothek<br/>lokale FLACs (Matching)"]
IA["interesting_artists.json<br/>Personalisierung / Vertrautheit"]
LOVED["loved_tracks.json + playlist_data/<br/>Loved- / Preferred-Tracks"]
RADIO["radio.py"]
M3U["Radio_<Künstler>.m3u<br/>lokale Pfade + YouTube-URLs"]
IINA["IINA"]
LFM --> RADIO
MB --> RADIO
YTM --> RADIO
BEETS --> RADIO
IA --> RADIO
LOVED --> RADIO
RADIO --> M3U --> IINA
classDef src fill:#e8f0fe,stroke:#3367d6,color:#000;
classDef script fill:#e6f4ea,stroke:#1e8e3e,color:#000,stroke-width:2px;
classDef out fill:#f3e8fd,stroke:#7b2ff7,color:#000;
class LFM,MB,YTM,BEETS,IA,LOVED src;
class RADIO script;
class M3U,IINA out;
| Achse | Lokale Umsetzung | Quelle |
|---|---|---|
| Ähnlichkeit | artist.getSimilar (Last.fms Similarity ist selbst CF-basiert, also ein guter Ersatz für Spotifys Audience-Graph), zusätzlich der related-Graph von YouTube Music und Member-Relationen | Last.fm; YouTube Music; MusicBrainz |
| Seed-Konzentration / Variety | Parameter: Seed-Quote plus ein Cap für Tracks pro Künstler (variety low = seed-lastig, high = breit gestreut) | Engine-Parameter |
| Popularität | Rang in artist.getTopTracks nach Listenern. Popular = oberer Rang, Deep cuts = unterer Rang plus Album-Tracks und Akustik- / Cover-Varianten | Last.fm artist.getTopTracks |
| Vertrautheit | familiar = Künstler mit hohen Eigen-Plays bzw. in der Künstler-Rangliste; discover = unbekannt, nicht in der Liste | Eigen-Plays aus der Künstler-Rangliste (interesting_artists.json) |
| Genre-Constraint | Tag-Match: dominante Tags des Seeds über tag.getTopArtists zu Genre-Nachbarn auflösen | Last.fm Tags; MusicBrainz Genres |
| Era | Release-Jahr-Filter über beets (year / original_year) bzw. MusicBrainz | beets-Cache; MusicBrainz |
| Mood / Energy | best-effort über Last.fm-Mood-Tags (chill, energetic) | Last.fm Tags |
| Recency | neueste Singles aus dem Orbit (Seed, Member, Top-Similars) in die ersten Slots, über die Release-Radar-Infrastruktur und den geteilten MusicBrainz-Cache | MusicBrainz |
Eine Achse hat lokal kein sauberes Pendant:
Spotifys Audio-Feature-Analyse (Tempo, Energy, Valence) lässt sich aus Last.fm und MusicBrainz nicht rekonstruieren, dort gibt es keine Echonest-artigen Merkmale. Das Mood-Tuning bleibt daher tag-approximiert und ungenauer als bei den Vorbildern. Eine echte lokale Feature-Extraktion über die FLACs (etwa mit
librosaoderessentia) wäre ein eigenes, späteres Projekt.
Die Pipeline: Eine Engine, sechs Phasen#
Daraus wird ein generisches radio.py. Nur Phase 1, das Bilden des Universums, hängt vom Modus ab; alles danach ist modus-agnostisch und teilt sich Bausteine mit daylist.py und match.py (lokales Matching, yt-dlp-Auflösung, Diversify-Tail).
flowchart TD
SEED["Seed: Künstler / Album / Genre / Era"] --> U["1 · Universum<br/>(je Modus verschieden)<br/>Seed + Member + Similars"]
U --> P["2 · Track-Pool<br/>Top-Tracks je Künstler"]
P --> T["3 · Achsen-Tuning<br/>familiarity · popularity · variety"]
T --> Q["4 · Quoten & Caps<br/>seed · member · collab · similar"]
Q --> O["5 · Reihenfolge<br/>Seed-Bias-Interleave + Diversify"]
O --> R["6 · Auflösung<br/>lokal: FLAC-Pfad · Rest: YouTube-URL"]
R --> M3U["m3u → IINA"]
classDef phase fill:#e8f0fe,stroke:#3367d6,color:#000;
classDef io fill:#f3e8fd,stroke:#7b2ff7,color:#000;
class U,P,T,Q,O,R phase;
class SEED,M3U io;
Implementiert ist bisher der Artist-Modus, also Phase 1 mit einem Künstler als Seed. Album-, Genre-, Era- und Season-Modi sind als Universums-Varianten vorgesehen, aber noch nicht gebaut.
Wie das Universum gewichtet wird#
Phase 1 sammelt Künstler in drei Töpfen und gibt jedem ein Gewicht. Der Similar-Pool wird bewusst aus zwei Quellen gemerged, weil der related-Graph von YouTube Music collaborator-nahe Künstler kennt (etwa Alex Goot), die Last.fm nicht führt:
seed Gewicht 1.0
Bandmitglied (aktuell) 0.85 (früheres Mitglied: 0.6)
Last.fm-Similar 0.5 × Match-Score
YouTube-Music-related 0.45 absteigend nach Rang (~0.45 … 0.22)
familiar-Boost auf bekannte Künstler:
Gewicht × (1 + min(Eigen-Plays, 200) / 50) → bis zu ×5
discover-Modus:
bekannte Künstler fallen ganz herausplaintextKonkret am Seed Against the Current: Chrissy Costanza zählt als aktuelles Mitglied (0.85) und ist besonders relevant, ganz wie Spotify die is-member-of-Relationen behandelt. Pale Waves und Maggie Lindemann sind Last.fm-Similars, die ich selbst viel höre, deshalb hebt der familiar-Boost sie nach oben, so wie sie auch in Spotifys Personalised-Tab aufsteigen. Ein Schlagzeuger ohne Solokarriere fliegt dagegen raus: Ein Mitglied muss eine echte eigene Hörerschaft haben (mindestens 2.000 Last.fm-Listener) oder selbst in meiner Rangliste stehen, sonst zählt es nicht als eigener Act.
Aus diesem gewichteten Universum zieht Phase 2 pro Künstler die Top-Tracks, und das Popularitäts-Tuning entscheidet, welcher Ausschnitt des nach Listenern sortierten Pools genommen wird: popular nimmt die Hits zuerst, mixed verschränkt sie, deep-cuts schiebt die drei größten Hits nach hinten und lässt zusätzlich Live-, Akustik- und Cover-Varianten zu (die im Default-Studio-Modus herausgefiltert werden).
Quer zu allen Töpfen liegt ein zweites Personalisierungs-Signal auf Track-Ebene: Meine Loved-Tracks, das lokale Gegenstück zum grünen Haken bei Spotify. Ein Loved-Track eines Künstlers wird in den Pool vorgezogen und bekommt im Score seines Topfs einen Bonus von 0,6, rückt also nach oben. Was als „loved” gilt, stammt aus zwei zusammengeführten Quellen, den Last.fm Loved Tracks (loved_tracks.json) und meinen kuratierten Künstler- und Album-Playlists (playlist_data/*.m3u), bei denen der Künstler aus dem Dateipfad gelesen wird. Beide Listen werden dedupliziert, ein Song in beiden zählt also nur einmal; --no-loved schaltet die Bevorzugung ab.
Phase 4 verteilt das Ganze nach festen Quoten, abgeleitet aus der Zerlegung eines echten Spotify-Radios:
seed 38 %
member 18 %
collab 10 %
similar 34 %plaintextDer Member-Cap skaliert mit der Länge (rund 16 % der Playlist, mindestens 4), damit etwa Chrissy-Solos ihren Spotify-nahen Anteil erreichen statt früh zu deckeln. Der Variety-Cap begrenzt, wie oft ein Nachbar-Künstler wiederkehren darf (low = 4, med = 2, high = 1 Track pro Nachbar), wobei Favoriten mit vielen Eigen-Plays ein bis zwei Plätze mehr bekommen. Vor allem anderen stehen die Recency-Opener: die fünf neuesten Releases aus dem Orbit, genau wie bei den Vorbildern. Phase 5 verschränkt das Ergebnis mit Seed-Bias (der erste Track ist immer der Seed, nie zwei Seed-Tracks am Stück), und ein Diversify-Durchlauf sorgt dafür, dass derselbe Künstler nicht zweimal direkt hintereinander läuft.
Das Ergebnis (mit Standardeinstellungen)#


Die Stellschrauben#
Out of the box ist das Radio seed-lastig und familiar, also nah am Spotify-Default-Gefühl: Vertiefung vor Überraschung, Discovery erst über explizite Flags. Lokal und YouTube werden adaptiv etwa 60/40 gemischt, erst die Bibliothek gefüllt, der Rest über aufgelöste YouTube-URLs, und beides vermischt statt angehängt, damit es wie ein durchgehender Stream wirkt. Die Chips und Regler der Vorbilder bilden direkt auf Flags ab:
| Flag | Default | Wirkung |
|---|---|---|
--artist "<Name>" | (Pflicht) | Seed-Künstler |
--length N | 50 | Anzahl Tracks |
--familiarity familiar|blend|discover | familiar | Vertrautheit: familiar boostet bekannte Künstler, discover lässt nur Unbekanntes zu (Spotify Personalised ↔ More discovery, YT Familiar ↔ Discover) |
--popularity popular|mixed|deep-cuts | mixed | Bekanntheit der Tracks; deep-cuts lässt Album-Tracks und Varianten zu (YT Popular ↔ Deep cuts) |
--variety low|med|high | med | Tracks pro Nachbar-Künstler (low = 4, high = 1; YT Artist-Variety) |
--fresh N | 5 | N neueste Releases aus dem Orbit ganz vorn (0 schaltet die Recency-Opener ab) |
--fresh-months M | 18 | Zeitfenster, ab dem ein Release als „aktuell” gilt |
--similar-artists N | 25 | Wie viele Similars ins Universum kommen |
--no-yt-universe | aus | Universum nur aus Last.fm, ohne den related-Graph von YouTube Music |
--local-only | aus | Kein YouTube, nur die lokale Bibliothek |
--full | aus | Den Seed-Playlist-Filter umgehen und alle Seed-Tracks zulassen |
--no-loved | aus | Den Loved- und playlist_data-Boost abschalten |
--dry-run | aus | Vorschau ohne yt-dlp-Auflösung und ohne Datei zu schreiben |
--no-open | aus | IINA nicht automatisch starten |
Die kuratierten Lieblings-Playlists, die ich je Künstler pflege (playlist_data/<Künstler>.m3u), greifen im Radio bewusst nur auf die Seed-eigenen Tracks, nicht auf die Nachbarn, sonst würde der Filter genau die Discovery abwürgen, für die das Radio da ist. --full hebt ihn auf. Die Pfad-Flags (--beets-dump, --ia, --loved, --playlist-dir, --out-dir) zeigen auf die Standardorte im Projekt und müssen selten angefasst werden.
Heraus kommt eine m3u_playback/Radio_<Künstler>.m3u mit absoluten Pfaden, deren Dateiname die abweichenden Achsen mitführt (etwa _discover_deep-cuts), und IINA startet direkt damit. Anders als die täglichen Playlists läuft das Radio nicht per Cron, sondern auf Zuruf, wenn ich gerade ein Radio für einen bestimmten Künstler will.
Stand und Grenzen#
Der Artist-Modus läuft und trifft das Spotify-Gefühl gut: Seed-lastig, mit Member-Solos, frischen Releases vorn und einer Genre-Nachbarschaft, die sich von familiar bis discover durchdrehen lässt. Die übrigen Modi (Album, Genre, Era, Season) sind als Phase-1-Varianten derselben Engine vorgesehen, aber noch nicht implementiert; der Season-Modus, der Tracks nach Jahreszeit aus den eigenen Scrobble-Monaten zieht, ist der schwierigste und kommt zuletzt. Und das Mood-Tuning bleibt die schwächste Achse, solange es lokal keine echten Audio-Features gibt, sondern nur die verrauschten Tags.
Das Setup hinter diesen Beiträgen#
Die Idee#
Ich baue Spotify-Funktionen wie Wrapped, Daylist, Radio, Release Radar und Discovery zu Hause nach, auf Basis meiner eigenen, in hoher Qualität gespeicherten Musiksammlung (FLAC-Dateien) und kostenloser Datenquellen. Ohne Abhängigkeit von Spotify, voll automatisiert, und Songs, die ich (noch) nicht besitze, kommen über YouTube dazu.
Jede dieser Funktionen erzeugt am Ende eine .m3u-Datei — eine simple Playlist-Textdatei, die entweder lokale Dateien oder YouTube-Links auflistet. Abgespielt wird sie im Mac-Player IINA.
KI als Kommandozeile#
Die Funktionen sind als Python-Skripte implementiert und können manuell oder automatisiert (cron) gestartet werden. bequemer ist allerdings ein KI-Tool, welches natürlichsprachige Anfragen interpretieren, ausführen und die erzeugte Playlist direkt abspielen lassen kann:
Erstelle und spiele ein Radio für “Against the Current”
Spiele Death Metal
Spiele 90er Metal/Crossover
Spiele die ersten beiden Alben von Gracie Abrams
Spiele das aktuelle Album von Taylor Swift
Die Datenquellen#
Vier Quellen liefern das Rohmaterial:
| Quelle | Was sie ist | Was ich daraus hole |
|---|---|---|
| Last.fm | Ein Dienst, der jeden abgespielten Song automatisch mitschreibt („Scrobbeln”) | Komplette Hörhistorie, Lieblingssongs („Loved”), wie oft ich was höre, „ähnliche Künstler/Songs”, Genre-Schlagworte, globale Popularität |
| MusicBrainz | Eine offene Musik-Enzyklopädie (wie Wikipedia für Musik) | Erscheinungsdaten neuer Releases, Band-Mitglieder, Genres |
| YouTube Music | Der Streaming-Dienst | (1) Abspielquelle für Songs, die ich nicht lokal habe — das Werkzeug yt-dlp findet die passende YouTube-URL; (2) ein „ähnliche Künstler”-Graph über die Bibliothek ytmusicapi |
| Lokale FLAC-Bibliothek | Meine tatsächlich besessene Musik, verwaltet mit beets (einem Musik-Bibliotheks-Tool) | Was „lokal verfügbar” ist, inkl. Künstler/Album/Jahr |
Dazu kommt eigene Handarbeit: kuratierte Lieblings-Playlists je Künstler oder Album (playlist_data/), eine Liste besuchter und geplanter Konzerte (concerts.json) und eine Einkaufsliste fehlender Musik.
Die Bausteine (Skripte)#
Kleine Python-Programme, jeweils für eine Aufgabe. Grob nach Zweck:
- Profile bilden — welche Künstler/Songs sind mir wichtig?
interesting_artists.py(Künstler-Rangliste),track_plays_snapshot.py,loved_snapshot.py. - Playlists erzeugen (die Spotify-Pendants) —
daylist.py(Mix nach Tageszeit),radio.py(Künstler-Radio),discovery_yt_playlist.py(neue, unbekannte Künstler),on_repeat.py,rediscovery.py. - Entdecken & pflegen —
release_radar.py(neue Veröffentlichungen meiner Künstler, als E-Mail),einkaufsliste.py(was mir noch fehlt). - Rückblicke —
wrapped_month.py(monatliche „Wrapped”-Grafiken),generate_topsongs_csv.py(Jahres-Top-100). - Migration —
match.pyordnet einen Spotify-Playlist-Export den lokalen Dateien zu.
Wann was läuft (Automatik per Cron)#
Cron ist ein Zeitplaner des Betriebssystems: er startet Programme automatisch zu festen Zeiten. Mein Zeitplan:
| Wann | Was | Wozu |
|---|---|---|
| täglich 09:00 | interesting_artists.py | Rangliste „wichtige Künstler” aktualisieren (Basis für Radio, Discovery, Radar) |
| täglich 09:30 | discovery_yt_playlist.py | Playlist mit neuen, noch unbekannten Künstlern |
| täglich 10:00 | on_repeat.py | „On Repeat” & „Repeat Rewind” |
| täglich 11:00 | wrapped_month.py | laufende Monatsrückblick-Grafiken |
| 6× täglich (0,5,8,12,17,21 Uhr) | daylist.py | Playlist passend zur Tageszeit |
| freitags 09:45 | release_radar.py (+ rendern + senden) | E-Mail mit neuen Releases |
| wöchentlich (montags 09:15) | Snapshots + einkaufsliste.py | Spielzahlen festhalten, Einkaufsliste aktualisieren |
| donnerstags 16:00 | Cache-Aufräumen | veraltete Daten löschen, damit sie frisch nachgeladen werden |
Das Radio (radio.py) läuft bewusst nicht automatisch, sondern auf Zuruf, wenn ich ein Radio für einen bestimmten Künstler will.
Caches (warum es schnell und höflich bleibt)#
Abfragen an Last.fm, MusicBrainz und YouTube sind langsam und haben Limits — MusicBrainz erlaubt z.B. nur eine Anfrage pro Sekunde. Deshalb wird jede Antwort lokal zwischengespeichert (ein Cache unter ~/.cache/lastfm-mb/,
aktuell ~150 MB). Die zweite Abfrage derselben Sache ist dann sofort da, und die Dienste werden nicht unnötig belastet.
Grob drei Gruppen: Last.fm (Hörhistorie, ähnliche Künstler, Tags), MusicBrainz (Künstler-Steckbriefe, Releases, Band-Mitglieder) und YouTube Music (ähnliche Künstler, Alben).
Wichtig: Manche Caches dürfen nicht ewig gelten — „ähnliche Künstler” und „neue Releases” sollen aktuell bleiben. Darum werden ausgewählte Bereiche wöchentlich gelöscht (donnerstags) bzw. beim Release Radar bewusst frisch geladen.