Brought my internet radio station into Gemini

Game That Tune Radio

Hi there everybody, just thought I'd share a small project I've been working on.

I've been helping run an internet radio station featuring videogame music, and I thought it'd be neat to give it a Gemini presence.

If your client supports it, you can stream music. There's links to a few different audio codecs (MP3, Opus, Vorbis, AAC).

You can also use a client certificate to register an IRC account, then use that certificate to authenticate. Our IRC chat has a chatbot for making song requests, saving favorites, things like that.

It's written using OpenResty (specically the stream-lua-nginx-module). It admittedly could have been a bit faster to use CGI in something like Polluxd but - I have a lot of other apps running in OpenResty, so going that route made sense to me, at least at first.

The radio streams over Gemini are basically proxies to the Icecast streams. But hey - you can listen to videogame music without ever leaving your Gemini client!

UPDATE: Of course after hitting publish I notice a typo! I wrote "specically" when I meant "specifically." I'm not sure how to go back and edit that.

Posted in: s/Geminispace

🎮 jprjr

Jan 25 · 3 months ago · 👍 stack, flipperzero, loopdreams, Homer, MikeK · 🔥 2

13 Comments ↓

🚀 stack · Jan 25 at 23:29:

Hit the edit button. If the post is not split into paragraph, hit the move/split button and enter S to split. Then, copy the paragraph you want to edit, click the 'replace' button and paste in the text, and edit it as you wish.

With LaGrange there are easier ways to do the same.

🚀 stack · Jan 25 at 23:35:

Thank you, I love it!

I wish there was a way to download your tracks -- I am often off-line but would love to keep these in the background!

☕️ Homer · Jan 27 at 11:50:

Hello!

That's a great idea. I take this opportunity to provide some feedback: the opus and acc options don't work either on gemini or web.

🎮 jprjr [OP] · Jan 27 at 13:04:

@Homer oh wow - I accidentally published wrong links for all the web links. Just fixed them.

For Gemini - did you try the Opus and AAC links in your client? That's likely an issue of the client not being able to decode.

You could use something like pxc or gemget to bring the data into a player like mpv, for example:

gemget -o - gttradio.com/radio/aac_320k | mpv -

or

pxc gttradio.com/radio/aac_320k | mpv -

🎮 jprjr [OP] · Jan 27 at 13:34:

Also regarding Gemini clients - different builds will support different codecs.

For example, on my Linux deskop Lagrange is built against libmpg123 and libopusfile, so it will play the MP3 and Opus streams. And I know off-hand that Lagrange brings its own Vorbis decoder, (stb_vorbis) so that should work on al platforms/builds.

My Android build of Lagrange only plays the Vorbis stream.

So, codec support varies.

🛸 bluesman · Jan 27 at 13:38:

I forgot to mention, all four streams play great in Alhena with embedded VLC. They also all work if you configure Alhena to use an external player. I use: ffplay -loglevel quiet %1

Cool station.

🛸 bluesman · Jan 27 at 13:43:

@jprjr Just FYI, I found out firsthand that the MacOS version of Lagrange doesn't play opus. I thought about re-encoding my own station to vorbis but it didn't seem worth it to me (all things considered).

🎮 jprjr [OP] · Jan 27 at 14:07:

@bluesman at one point I had grand plans for the web front-end to offer multiple streams with sample-accurate playback. So you could have say, AAC-LC, xHE-AAC, and FLAC streams, all in HLS, timed ID3 metadata, with the correct timing/padding info that you should be able to switch between streams seemlessly.

I wrote a tool to do all that from a single source FLAC stream - https://github.com/jprjr/icecast-hls

I was using Icecast to host the source FLAC so I figured, I should add Icecast output as well.

And now - the web front-end just has the single HLS stream and doesn't use any of the embedded metadata (it gets it out-of-band) and I find myself using the Icecast streams way more often!

🎮 jprjr [OP] · Jan 27 at 14:15:

But anyways, that may make it easier to offer multiple encodes, though I admit - I'm pretty certain something like ffmpeg could handle multiple encodes.

I'm unsure if ffmpeg offers the same metadata feature. Basically - I use a chained FLAC-in-Ogg bitstream to have updating metadata, and that metadata gets passed along to the final outputs. Either as timed ID3 for HLS streams, or chained Ogg bitstreams for Vorbis/Opus on Icecast.

Last I checked ffmpeg only decodes the first set of tags in chained Ogg/FLAC https://trac.ffmpeg.org/ticket/9778

🛸 bluesman · Jan 27 at 16:52:

I'm using a reverse proxy to serve the songs off a pi 5 in my house so I wanted low bandwidth, reasonable quality and I didn't want to re-encode. I jumped through hoops getting liquid soap running on the pi. The default install would seg fault. Why liquid soap? It's the only way I could figure out how to get a randomized song order on each iteration - at least without disconnecting clients when the playlist "recycled". Metadata was a nightmare. I gave up on having per song metadata and just set info for the entire stream.

All the tunes are served out of a ramdisk so I don't destroy the poor SD card over time.

It was a fun learning experience for sure. Not a lot of listeners though. No surprise. I can say with absolute confidence it's the only 100% original music station in Geminispace.

🎮 jprjr [OP] · Jan 27 at 17:53:

At one point I looked into Azuracast, which I believe integrates liquidsoap. It's pretty sweet but complex.

Mine is using Music Player Daemon, with an app I wrote (the chatbot) that connects to it and controls it, ensuring there's always music in the queue.

I know what you mean about the client disconnects - for MPD, I had to set a global sample rate + bit depth + channel count. Usually if any of those parameters change between tracks it disconnects clients, which makes sense.

MPD supports setting it per-output - but if you do the global setting, that also enables crossfading between tracks with different properties, since they all get normalized.

☕️ Homer · Jan 28 at 15:35:

I forgot that Lagrange didn't have support for some of the codecs and that's why they didn't work. Sorry.

🎮 jprjr [OP] · Jan 28 at 17:03:

@Homer all good!! I didn't realize I typo'd the web links and you helped me fix that