Karl Erik Hofseth

GraphicAudio has a terrible app—let's circumvent it

2021-06-26

4 minutes read

About a year ago, I had a problem: GraphicAudio's app is terrible. Let's back up a bit.

Background

There's a company called GraphicAudio, who make really good dramatised audiobooks. That is, audiobooks with a full cast of voice actors, sound effects, intense music, etc. Specifically in my interest, they've adapted most of Brandon Sanderson who is one of my fovourite authors. The problem? Their app is shit.

The Graphic Audio logo
Giving me real "it's not porn it's HBO!" vibes with the name there.

Ok, so their app does technically work. You can download books and listen to them, and it doesn't reset your place or anything. It's just generally bad. It doesn't group by book or series (so you have to interact with the "part 1 of 5" individually), it has no automatic download or cleanup, when paused it can't be unpaused from the button on my headset (requiring instead that I get my phone out), and it's just generally a pain to use.

The Idea

I also listen to a lot of podcasts using the brilliant app Podcast Addict, which consistently never gives me troubles. And GraphicAudio allows you to download the audiobooks as plain audio files. Solution? Turn the audiobook into a podcast!

XML, RSS, and Podcasts

Podcasts are one of those old technologies on the internet, still based on an open and decentralised standard (though Spotify is trying to change that, to everyone's detriment). It's an RSS feed. That's it. It's an RSS feed and a place to host audio files.

This is what makes podcasts brilliant, in my opinion; the total freedom of choice on all ends of the system. I can choose any of hundreds of podcast apps for Android, and the podcaster can choose any of hundreds of places to host their podcast. This is, I think, as aspect of the Internet which is slowly dying out. Video is all on closed platforms (YouTube, with a smattering of Vimeo) and streaming services, and none of these allow the kinds of API access to use whichever client you want. Even podcasts are under attack, as Spotify seeks to usurp their place with their exclusive audio shows.

Generating the podcast

Here comes the first technical details: taking the folder of mp3s and generating an XML file to describe it as a "podcast". There are plenty of products/platforms which can do this, at least for actual podcasts, but finding a good tool designed to work with just a folder of files was kind of tricky.

Thankfully, I was not first in this pursuit. The wonderful Marcel Bischoff had apparently had this problem before! And he decided to share his solution under the ... interesting? ... name of Screaming Liquid Tiger

Screaming Liquid Tiger
There are zero answers about the name. Also, go women in Zanzibar!

I think this was intended to be used on an actual web server, generating the XML on demand on some web host. Given that PHP runs pretty much literally everywhere (even where it shouldn't) this probably does that quite well. PHP does not, of course, run on a static file host like Firebase Hosting.

My solution was to download PHP, install it on my machine, and run the script locally.

First set some config variables:

$conf = array(
'description' => 'Stormlight Archive',
'link' => 'https://imnot.telling.you',
'title' => 'Stormlight Archive',
'image' => 'cast.jpg'
);

Then make sure to supply the right base url about halfway down the file:

//$base_url = str_replace("index.php", "", $prot . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"]);
$base_url = "https://firebasestorage.googleapis.com/v0/b/imnot.telling.you/o/Stormlight%20Archive/";

The script is originally intended to figure out the base url for all the files on its own using the server environment variables, but this doesn't work locally. So I just had to plop in the url to the folder on firebase Storage where I put the files. Before we actually run the script, though, let's set up our hosting environment.

Setting up Firebase Hosting

This part is thankfully quite easy.

With the firebase-cli installed and a project created in the dashboard, all we need is firebase init, and it will guide us through the process. Once we have the hosting set up, we can go ahead and run the script:

php index.php > "..\Firebase Hosting\public\Stormlight Archive\podcast.xml"

And then just firebase deploy --only hosting and the XML is live!

Uploading the actual audio files to firebase Storage was a slight pain because some of the uploads seemed to time out eventually, but with a little perseverance and a little batching I got them all uploaded and ready (in fairness, uploading all of The Way of Kings, Words of Radiance and Oathbringer all in one go does net about 12.5 GB total—and we can see why I didn't want to keep all of it on my phone at all times).

The result

Stormlight Archive playing in Podcast Addict
It's beautiful. And yes, I did start at the beginning for this photo. I binged the series last fall.

By setting up a new podcast in Podcast Addict that just points to https://imnot.telling.you/Stormlight%20Archive/podcast.xml I can use all my favourite features! Automatic downloading and cleanup is the biggest one for me, so I can always have at least a couple of hours of audiobooks available without filling my device with chunks of 4GB per audiobook. I can now resume playback with the headphone action button (something GraphicAudio Access loudly ignores).

This is now my system for listening to audiobooks (at least the ones from GraphicAudio). I have folders set up for this, and keep the script ready to set up new audiobooks with only minor tweaks (basically the name). And the whole thing is basically free on Firebase since I'm the only one using it.

A word of warning though: I haven't shown you the urls and domains used for this, because there really isn't any protection on this. Now, the worst anyone could do is commit a bit of piracy and run up my bandwidth charges on Cloud Storage until I noticed, but I'd still prefer to avoid that. It is possible to require user authentication for the actual audio files, but Podcast Addict doesn't exactly integrate Firebase Authentication. It's probably fine (good luck guessing all the urls I guess), but still beware.