adikos.net

So You Wanna Scrobble

Now some of you may be asking, what the hell does "scrobble" mean? Well, it's a nonsense word for the most part, but it means "to submit your currently playing song to a service which tracks your listening history." Back in the early 2000s (2002 per a search just now), a service spun up called Audioscrobbler. The idea was that you'd play music, and your music player would send metadata about the song you were playing to Audioscrobbler's site, and eventually it would build up a sort of personal listening profile of you. You could share it with friends and say "hey, look at all the cool music I listen to! You should too!" or whatever. Or you could learn about others' music taste in turn, and discover new artists. It all started out very inauspiciously and homebrew, very chill. Eventually the venture capitalists and music industry took notice, and well, y'all know what that means. It became corporate and boring and annoying. The service rebranded as Last.fm, which was a more suitable name for the service, probably, but it was never the same. I don't like it anymore.

I was on Audioscrobbler/Last.fm for years and years, with thousands and thousands of playcounts. Eventually I left it, though, and decided to go with a more smallweb solution called Libre.fm. That site is fine, but it's very barebones, and I'm still having to submit data to somewhere I don't control. In an age where we have very little control over our data floating about in the world, I try to retain as much as I can. Hence this server, and its services, and whatever other smallweb things I use that largely circumvent the easy access, data-hungry corporations everywhere.

When looking for a Libre.fm alternative, I found ListenBrainz, which seems to be a pretty non-corporate, nice site for submitting listening data and such. It's associated with MusicBrainz, which in general is focused on correctly cataloguing music metadata. All for that. I found out that my music player of choice, Strawberry Music Player, is able to scrobble to ListenBrainz. Awesome! I just have to put in my API key for ListenBrainz (easily available in your user settings on the site, known as the "user token"). So that's pretty cool. I highly recommend it if you want a no-fuss alternative to Last.fm.

However, I was talking to one of my friends, and she said she self-hosts a software package called Koito which does pretty much the same thing. I looked at her Koito instance and thought it was super, super cool. And if you know anything about me, you know I'm down for self-hosting just about anything I can shake a stick at. Why not host it myself and keep all the data somewhere I control, rather than sending it elsewhere? So I thought, awesome, let's do this!

As you may know from perusing elsewhere on my site, I run my server on YunoHost, which is lovely. They have apps for most of the things I want, but unfortunately not everything. I found that the recommended easiest quickstart for Koito is via Docker, a system which, as far as I can tell, lets you create little "containers" for webapps to run on your server. Not dissimilar from YunoHost, but works a little differently. YunoHost has some limited documentation on installing "custom apps," but it was not very helpful. As usual, I found a YunoHost forum post, which, while it bumbled through things a bit, still helped me get started. I spent part of a weekend day setting up Koito according to those instructions, and then found that I couldn't set a custom ListenBrainz API URL for Strawberry. That's on me; I put the cart before the proverbial horse. So back to ListenBrainz I went, but I still wanted to find a way to use Koito, whether that meant changing music players or what.

I had an idea: what if I could get another intermediate program to "listen to" (i.e., track) what I was listening to in Strawberry, and then pass it along to Koito? That way I could set up a custom ListenBrainz API url and point it at Koito, rather than the official ListenBrainz site. And then we'd be all good. I really lucked out, because I found a small but mighty program called rescrobbled which uses MPRIS (Music Player Remote Interfacing Specification) to read the currently playing track. And Strawberry definitely uses MPRIS, since you can control it with a widget on the panel. So I think I found my pipeline: Strawberry -> MPRIS -> Koito! Now, if you're using a music player that allows a custom ListenBrainz URL, you can certainly omit the rescrobbled step, and just point it at your Koito API (https://<your Koito instance>/apis/listenbrainz/1 should work)

Installing Docker & Koito

Now, I can only speak for my experience using YunoHost (on Debian Linux). Your installation steps for Docker may be way different. Basically, install Docker on your system, whether it's local or on a VPS. If you've already installed it, and set up the Docker daemon to start on boot (these instructions are for systemd on Linux; YMMV), then move on.

If you're running Koito on a domain or subdomain, set that up, either on your computer, or in your DNS settings on your VPS. Everyone's installation is a bit different, so I can't provide for all those permutations. However, if you're setting it up on YunoHost, set up a domain/subdomain, then do the following:

Once Docker is installed and ready to go, you're ready to start installing Koito. Koito's quickstart suggests using Docker Compose, which seems to be an easier way to set up a Docker app container. Docker Compose uses a .yaml file for its configuration. I am really unfamiliar with yaml, except for using it a bit with Hugo, but it seems easy enough to follow. And the sample compose.yaml (I called it docker-compose.yaml on my installation) is an easy skeleton you can modify. Here's mine:

services:
  koito:
    image: gabehf/koito:latest
    container_name: koito
    depends_on:
      - db
    environment:
      - KOITO_DATABASE_URL=postgres://postgres:<PostgreSQL password>@db:5432/koitodb
      - KOITO_ALLOWED_HOSTS=<your Koito instance URL>,127.0.0.1:<4110, or your Koito port>
	  <note: optional parameters>
      - KOITO_ENABLE_LBZ_RELAY=true
      - KOITO_LBZ_RELAY_URL=https://api.listenbrainz.org/1
      - KOITO_LBZ_RELAY_TOKEN=<your ListenBrainz user token>
	  <note: end optional parameters>
    ports:
      - "4110:4110" <note: you can use whatever port you prefer, but Koito defaults to 4110; use this above in KOITO_ALLOWED_HOSTS also>
    volumes:
      - ./koito-data:/etc/koito
    restart: always <note: I set this to "always" instead of "unless-stopped" so it would start on boot with Docker>

  db:
    image: postgres:16
    container_name: psql
    restart: unless-stopped
    environment:
      POSTGRES_DB: koitodb
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: <PostgreSQL password>
    volumes:
      - ./db-data:/var/lib/postgresql/data

So that's my Docker Compose config file. A few notes on some of the parameters within (please remove any <> part with note: at the start of it from your file!):

Once you've set everything up within, you're ready to spin up the Koito instance:

Setting Up Your Music Player

So now we've got Koito set up. But we need to set our music player up to submit its plays to the Koito instance. As I mentioned above, if you have a music player that will accept a custom ListenBrainz API URL, go ahead and set it to the following: https://<your Koito instance>/apis/listenbrainz/1/

However, if your music player, like mine, will only allow scrobbling to the main ListenBrainz server, then we need to take a different tack. This is where the little program rescrobbled comes in.

[[listenbrainz]]
url = "https://<your Koito instance>/apis/listenbrainz/1/"
token = "<your Koito API key>"

Make sure you pull your Koito API key from the Koito instance in Settings -> API Keys.

I also highly recommend setting up rescrobbled as a systemd service; the service file is provided by the author, and needs to be placed in ~/.config/systemd/user. Go ahead and follow the rescrobbled instructions here under Usage to set up the systemd service. That way you can have it start every time you fire up your computer.

Now, go ahead and play your music; it should all send to your Koito instance (and ListenBrainz, if desired, via the relay), either directly from your music player, or via rescrobbled!

Koito & Streaming Apps

Let's say you, like me, are super geeky about all of this. Not only do you want to track music played on your computer through Koito, but also through your favorite streaming app. I prefer to stream music via my phone a lot while I'm working, since I don't have my (personal) laptop running during that time. Best case scenario is if you can find something that will allow you to access it through a Subsonic-compatible client. I use DSub2000 (available on F-Droid) personally. DSub2000 will let you set it to Scrobble to Last.fm (Settings -> Playback), which of course can use ListenBrainz as well.

Here are a couple of good options for self-hosted music streaming servers:

Basically, decide on a solution, and ideally it'll let you specify a custom ListenBrainz URL. Below, please find how I got Funkwhale to work with Koito (hacky workaround, but oh well).

Koito & Funkwhale

Once you've installed Funkwhale (pretty straightforward via YunoHost), we have to do a little manual tweaking. Now I don't mean just tweaking the configuration. That part is relatively easy, but this is a little more obscure. Funkwhale's ListenBrainz plugin is hardcoded to access only the main ListenBrainz server. That's all good and fine if we're just scrobbling to ListenBrainz, but we presumably would like to send it to our Koito server instead, which, again, can handle ListenBrainz requests just fine. At the time of writing, the most recent Funkwhale version is 1.4.1, which has integrated an old ListenBrainz scrobbler plugin that still works just fine. I looked at the code for the development branch, and they seem to have ditched this plugin for a Python library called liblistenbrainz, so we may have to update this tweak whenever that ships. It's fine.

So the nice thing is that this is all open-source, right? So we can modify the ListenBrainz plugin to point at our Koito server instead. I really wish there were a GUI option for this, but oh well. We make do. Now follow these steps:

Now that Funkwhale knows how to send scrobbles to your Koito server, you can follow the Funkwhale ListenBrainz plugin documentation and enter your API key from Koito. I'd recommend generating an API key for Funkwhale too (see instructions above). Now login to your Funkwhale server on your streaming app (via Subsonic ideally), tell it to scrobble, and it'll use the info saved in Funkwhale to route that correctly! Yay!

Koito & Navidrome

In Navidrome, we have to do a few things before we can set up scrobbling to Koito or another ListenBrainz-compatible instance. This involves manually editing the navidrome.toml file, which is the configuration file. There are a ton of options within, but only one that we care about for our purposes.

# ListenBrainz for Koito
ListenBrainz.BaseURL = "https://<your Koito instance>/apis/listenbrainz/1/"

You should be all set now! Go and enjoy sharing your music taste with the rest of the world, and also enjoy looking back at trends in your listening habits! I'm happy to try to answer any questions I can otherwise. Thanks for reading, friends! <3