onlytomorrow void

writing into the void!

"Self-hosted music on iOS"

I hate using my iPhone, it's awesome

posted on 2024-08-21 by: kirby | 12 min read


Preface

Over the years, I’ve grown to dislike Spotify. Its discovery algorithm is not as it used to be (no joke, YouTube gets me better recommendations at this point), and I’m not really into their push of podcasts onto the same app.1 Early on in 2023, I had spun up a home server with a pretty cheap mini PC I got online. There were many discussions I had been reading for self-hosted options of streaming your own music library as an alternative to Spotify. The migration began — I wanted to make use of my stagnant music library that had higher quality audio than what I was paying for on Spotify, and have it all conveniently organized and controlled on a whim by me from any device.2

This post will outline all the options I’d tried for making self-hosted music streaming work for my use case specifically on iOS, since it was the biggest pain point in my whole setup that just didn’t hit the mark compared to everything else: gapless playback is hit-or-miss, offline downloads sometimes works, and the UX of many apps is laughably clunky. Hopefully this may guide you if you ever try to attempt this and also have an iPhone. Any ol’ Subsonic-compatible server can reasonably run on a VPS, though I have no advice for hosting your music library on someone else’s computer.

The server

My home server is nothing special or elaborate. The mini PC has an Intel Jasper Lake CPU (for Jellyfin transcoding), and 8 GB of RAM. I also threw in one of my old SATA SSDs for storing all of my FLACs and Linux ISOs.3 It’s running Debian 12, with most of this stuff being stored and managed with Docker containers. The machine is perfectly capable of running Proxmox, but this is already such a lazy setup I figured I would do it “right” once I upgrade my hardware, particularly the storage (if ever).

Subsonic

Subsonic is a self-hosted music server that has an API used by many current popular alternative music servers. In particular, the most popular/recommended one is Navidrome, which is compatible with the API. This is important because most music player apps on all sorts of devices generally support only the Subsonic API, but not everyone is willing to pay a premium to use the Subsonic server specifically.

Accessing/downloading the music

Over the years, my music collection has been very lazily sorted just by a simple folder-based system. A folder for the artist, and in there a folder for each album/release. For example, a directory would look like ~/music/Death/(1988) Leprosy/. Within that release’s folder, folder.jpg is its cover in a reasonably high resolution. My whole music collection is now living on my server and I have some services to help collect and manage new music. Soulseek does the heavy lifting on the collecting front, and I won’t elaborate further. ;)

Initially, I didn’t use Navidrome mostly because I wasn’t going to use the accompanying web UI that it deploys. 99.9% of the time, I will use a music player like foobar2000 (on Windows) or Strawberry (on Unix-like) that can access the server using Subsonic’s API. Instead, I set up gonic, which is a more simple music server that focuses on folder-based libraries. Its web UI is very straightforward and used purely for configuration. It worked well enough for a few months — it supports last.fm scrobbling and other API usage, scanned my library pretty fast, and was pulling off quick transcodes. This is where it gets a bit complicated and nitpicky.

gonic

gonic, for how lightweight and fast it was, was unfortunately missing some nice-to-have features. Scanning folders was fast, but transcoding options are pretty bare-bones. I store my music in FLAC, and when I want to listen on my phone, I want the music converted to something lossy for offline listening while saving space.

gonic

The gonic interface lets you configure which type of client gets transcoded music. However, it doesn’t let you configure the various transcoding profiles themselves very easily, instead only gives a select number of profiles, as outlined in the project’s wiki. With that in mind, I configured every connected client to use 128kbps Opus. I didn’t feel like digging through server logs each time I tried a new iOS client.

In theory, setting all clients’ music to be transcoded would work well, but it seemed like the apps I ended up using on iOS were not following this transcoding profile 100%. ReplayGain also seemed to be on for every transcode, despite me not choosing ReplayGain (opus_128 vs opus_128_rg) — it made every song sound like shit when peaking from my phone; it was as if it was playing off of FM radio. I quickly set up Navidrome after realizing this, and ditching gonic altogether.

Navidrome was about as simple to set up as gonic, and the web UI works for what it is and follows Material Design. Folder scanning is fast and easy, and it picks up all of my tags and playlists with no problem. There’s even a color theme to make the web UI look like Spotify. Most importantly, ffmpeg transcoding profiles can be added and edited whenever I want!

navidrome tc

Now that I had that figured out, I needed an iOS app to stream and download my library in a transcoded format. Before I get into setting it up to transcode properly, let me outline the bulk of this post: what I think are the only reasonable choices iOS users have for streaming and downloading their self-hosted music.

Note that I am not interested in using Jellyfin for both music and TV/movies. I prefer the separation of the two. My music server is purely for myself and my weird ass tastes, while my Jellyfin server has a handful of users accessing the same library.

Self-hosted music iOS apps

Thanks to Apple and its stupid ongoing yearly developer fees, commissions, and requirements of using a Mac to make any of these apps work, iOS users have always got the shit end of the stick for open-source and self-hosting related apps. There are free options, and paid options. I needed the following criteria to be met for it to be good enough for my use case:

I suggest you view this table of clients and servers with Subsonic API compatibility: especially if you’re looking for a decent desktop program or Android app. Android has way more choices and honestly better apps, but I’ll take what I can get.4

Below are my top three choices for iOS that met most or all of the requirements, from “worst” to “best”.

Substreamer (free)

Substreamer is the first app I tried. It’s free, has an okay-looking user interface, and supported offline mode and downloading. It met almost all of my criteria. However, offline downloads sometimes didn’t complete correctly, and incomplete downloads that appeared “complete” had very obvious skipping and errors in the “final” transcode that is downloaded. Worst of all, gapless playback is still a work-in-progress feature. This is pretty much a dealbreaker. I’m still an album listener first and gapless playback is pretty much a requirement.

iSub (free)

iSub is a very straightforward music streaming app. The user interface is a bit outdated, but it met nearly all other requirements. Gapless playback worked, offline caching was smooth, and viewing my albums and playlists was simple.

isub homeisub settings

Eventually, I ran into issues with sorting music in its list interface,5 and there was pretty much no CarPlay support. Half of the pages on the interface don’t really work as expected, or spit out errors in the Navidrome server logs. It’s likely due to Navidrome not being 100% compatible with the Subsonic API. The app is also in maintenance mode, with no further updates planned. If the interface looked more up to date, I would be okay with this, but there is a lot of room for improvement with this app.

isub controlisub tc

Regardless of my nitpicks, if you’re looking for a simple and 100% free iOS app to use with your Subsonic API-supported server, it should be iSub; simply because of its featureset, and not for its visual design. Seriously, take a look at the Now Playing screen; it’s flat as shit and looks like it hasn’t been changed since iOS 7’s design guidelines.

play:Sub ($5)

The situation was getting desperate and I looked to the paid alternative that was consistently recommended online: play:Sub. This app, so far, has met all of my criteria to an acceptable degree. My one main nitpick with this app is that the Now Playing screen is way too busy with so many irrelevant buttons. On this page, the track info is also displayed on top of the cover art. It hasn’t bothered me much yet, but I know it would for other people. I much prefer iSub’s Now Playing screen over this.

playsub npplaysub controlplaysub ui

Maybe it’s my mini iPhone that makes this look more busier than it is, but seriously, let me disable like 50% of these buttons on-screen and let me organize it how I want. You can configure many options for album views, tabs, and defaults, but the Now Playing configuration is laughably bare. It doesn’t entirely prevent me from using this app, so I will just live with it. play:Sub is well-supported by a solo developer, and I’ve had no further issues aside from my nitpicks, so I will be sticking to this app for the foreseeable future.

High quality offline downloads

With the app settled, Navidrome made it super easy to set up play:Sub with transcoding at my desired quality. Once it was configured, I have yet to experience issues with random ReplayGain or large download sizes on my phone’s storage. Since Navidrome only transcodes when I listen from my iPhone, I can happily listen to my FLACs directly through the Strawberry player on desktop.

navidrome app tc

Downloading converted music for offline listening on my phone also turned out to be the fastest with play:Sub - one song takes only a couple of seconds to transcode and grab from my server. The download progress is accurate and actually works flawlessly in a pinch. CarPlay support is excellent and is very much like Spotify’s, where it just works. Now, I’ve reached a point where I’m happy with how my setup interacts with iOS, and vice versa.

The complete setup

In summary:

Navidrome is my music server of choice, set up alongside my collection on my home server. I access my home server remotely with a VPN (in this case, Tailscale/Wireguard) on my devices. For music on my iPhone, I use the play:Sub app to download, listen, and scrobble. It’s all on my own terms and my library is under my control. For logging my listening habits for purely superficial “social” reasons, last.fm scrobbling works effortlessly and doesn’t randomly stop working like Spotify did every few months.

playsub size
This is about 80 albums downloaded offline on play:Sub. Spotify would somehow take up to 2x the size for the same pool of albums downloaded, and at a worse quality.

For transcoded audio from FLAC, 128kbps Opus is pretty much indistinguishable from lossless (especially when I listen from my shitty AirPods Pros, this is all subjective of course) and the space savings when I download my music onto my phone are very much appreciated. On desktop, I can listen to FLACs with no issue, and on-the-go I’ll have little to no compromises on audio quality. I’ll take this over Spotify any day.


Footnotes

  1. Some people would stick on Spotify no matter what for its social features, and features like Spotify Connect. Personally, I have not really used these social features much recently. For example, Blends: these auto-generated playlists never turn out well in my experience, maybe the algorithm hates me? Jam sessions? I dunno, I just request a song to a host verbally. Fuck scanning codes with my phone. And finally, Spotify Wrapped, which now gets cloned by Apple Music and even last.fm to varying levels of success. As for Spotify Connect, I haven’t really used it at all recently. It used to be great, but now sometimes does not play the correct song or is mixed up with whatever was playing on the other device. I’m not personally attached to any of these features, as music discovery was my main hook to Spotify over the years.

  2. For years I had been back-and-forth listening from my local music library and using Spotify for everything else out of laziness. Spotify’s local file support is straight up garbage on any device, and usually requires some stupid firewall trickery to get wireless downloads working. Apple and Google have had this figured out in iTunes and formerly Google Play Music respectively, for like 10 years now, how could Spotify not get this feature working as smoothly as its competitors?

  3. There is also an external 4TB WD drive that I had laying around plugged in to one of the USB 3 ports on the server. That’s for a lot of Linux ISOs.

  4. I still prefer iOS over Android. Let me know when an Android manufacturer makes a flagship phone as small as an iPhone 13 mini with at least half a decade of software support and maybe I’ll look into it.

  5. Multi-disc and “Various Artists” albums didn’t appear as expected in the app’s lists — it could’ve been how I tag my music, but I could not be assed to manually change this in kid3 or adjust my folder structure to appease this aged app’s conventions.

learn html flashpoint pm me plsss stay down chrome sux vegan nekoscape