DIY internet radio
An easy choice of one's own music in a living room is nice. We used to use our smart TV, but when its app store and support stopped existing it became a dumb TV again.
I wanted to make something easier to use, and unobtrusive.
I wanted something as basic as possible.
This is why it's
- a pushbutton to change station and turn off
- short press goes to next station
- long press turns it off
- a SSD1306 style OLED display
- in part because it's small and cheap, in part because I think it's more elegant that it makes no light when off
- showing current station, and whether we're connecting or playing
- a box holding the raspberry
- a piece of nice looking laminate flooring in front.
- holding the button
- and the display - with a 3D printed
I should probably countersink the screws a little better, but I'm sort of fond of the DIY look.
Platform and software
I considered an ESP8266 or ESP32, also for the sake of learning how to abuse it for this, which shouldn't be hard since (other people have already made this), but I figured its PWM-based audio would probably not be great, and the point was nice music.
So I settled on a Raspberry Pi (which is still PWM-based, but faster and probably more regular), and that platform also makes it a little easier to deal with changing changing stations and code by SSHing in, dealing with less-usual stations in code, and I had some worry about TLS though most stations don't put their stream on that.
Also it already has an audio jack. Don't make projects harder than they need to be, y'know.
There are various ready-made things to do web radio and more.
- Those either leave a lot to be duct taped together (MPD+controller interface)
- or are too fancy, e.g. giving an interface much more complicated than I need (e.g. volumio)
I had some practical worries. Say, some radio stations change their stream URL over time. That's easy enough to work around with a few lines of screen scraping code, not so much if all you get is "add shoutcast URL here".
But more importantly, integrating that display and button into anything would be as hard as writing my own.
That, and given that the functionality is so very basic, I wrote my own.
It's a ~200-line, quick and dirty python script that mostly just runs ffplay,does a before switching to a new station, and determines whether something is playing by using to see if something has an ALSA device open. I'm not sure it's even worth cleaning up.
It relies on CircuitPython for the button (GPIO interface) and display (I2C, and existing SSD1306 library), and ffmpeg for playing.
One's own music as web radio
One easy-enough way way to put your own music on a standard shoutcast-style stream to point a standard internet radio player at is ([little more on how those work here]) is a little server that runs:
- [https://www.streambox.org/elc/software/icecast.htm Icecast2 (or similar)
LiquidSoap is a flexible tool (to the point it's a little hard to get started with), but I use it mainly to read a playlist.
After some experimentation, each station amounts to a configuration like
out = output.icecast( %mp3(bitrate=160, samplerate=44100, stereo=true), host="localhost", password="hackme", name='piano') list = playlist( mode='randomize', '/Music/ice_play/piano.m3u8' ) default = single( "/etc/liquidsoap/Silence.ogg" ) s = fallback( [list,default] ) # TODO: figure out replaygain's rough edges skys = sky(rgs) # multiband compression, makes some sense for quiet listening #rgs = crossfade(start_next=2.,fade_out=2.,fade_in=2.,rgs) out( mount="piano", add( [ skys ] ) )
One downside to this approach is that this radio is always running, i.e. each channel always runs its encoder , each using maybe ~10% of a CPU core, regardless of whether anyone is listening.
There are ways around that - by not using shoutcast, and writing a bunch of custom code. So I didn't do that yet.