BIT-101
Bill Gates touched my MacBook Pro
I’ve been getting heavy into internet radio lately, as mentioned in this post and that post. A lot of what I listen to day to day is just music of a specific genre. You just let it play and it’s the same general stuff all day. But there are also some local stations and college stations, as well as NPR affiliated stations that I listen to that have schedules of different shows at different times of the day and week. Some of these are a DJ playing a specific type of music for an hour or two, or maybe a live show, sometimes interviews, news, talk shows, etc. Since these come on at specific times of the day, you either have to listen to them when they come on, or maybe they have an archive you can listen to some time later. Or… you can record them.
I spent a lot of time thinking about recording hardware. I considered getting a new or vintage cassette deck. I looked into hifi hardware digital recorders. There are surprisingly few of these, and they are outrageously expensive. I’m really surprised there aren’t more devices like this. It would just take an audio capture board and an SBC (single board computer) and some software and buttons. I started looking into making one myself. A raspberry Pi with an audio hat. But goddamn, rPis are so expensive now. rPi 5 with 4GB RAM is over well $100. 16GB is $350. That’s before you get a case and a power supply and a cooling fan and the audio hat. I looked into other boards that are less expensive, but in the end I changed gears a bit.
I decided to do it all in software. ffmpeg can record an live audio stream, like so:
ffmpeg -i https://some-audio-stream -c copy recording.mp4
So simple. But there’s so much more you can do with it. I wanted to be able to schedule future shows - have it start at a specific time. And record for a given amount of time - 30 minutes, an hour, two hours, whatever. And I didn’t want to have to type in streams, just the name of the station.
So I built a little command line app in Go. It calls out to ffmpeg to do the actual capture and save, but it takes care of the scheduling, catalog of stations, text ui, etc. It does almost everything I need it to at this point, but I still have ideas for more features.
It’s called recplay because it records and plays streams, but also because on the old cassette recorders I had as a kid, you had to press the record button AND the play button at the same time in order to record. See the image at the top of the page.
Here’s the help to give you an idea of how it works:
In general, you specify a stream/station, and a date, time and duration to record, and an output file name. But you can skip most of those.
Or, you can choose a station and play that station without recording.
Here’s the list of stations, so you don’t have to remember long stream URLs:
If you just specify a station, it will start recording immediately for a default 30 minutes.
Also notice that if you don’t specify an output name, it makes one up.
If you want a longer or shorter recording, change the length.
If you want to record at a specific time, you can do that. Without a date, it assumes today.
Or specify another date.
Of course, on *nix systems, you can throw a & on the end of the command to background it. It’ll still record and exit when it’s done.
I’ve been using this all weekend, scheduling and recording all kinds of streams, and listening to them later. One of the biggest pain points was making mistakes in choosing the right date and time. Especially remembering that it has to be in 24 hour time. I’d type 08:00:00 thinking it was 8 pm, not am. So I fixed that up a bit…
Still, sometimes I mess up and wind up with a date/time that’s in the past. In that case, the app will start recording immediately, confusing me. So I patched that one…
Initially of course, I hardcoded the station list, but eventually I knew it’d have to be externally editable. Now, when you start the app for the first time it looks for a config file in the system user config location. If it’s not there, it creates it with a few sample stations. This is just a json file that looks like this:
{
"WERS": "https://15313.live.streamtheworld.com:443/WERSFM_SC",
"WMBR": "https://wmbr.org:8002/hi",
"WVEW": "https://audio-edge-n9hx8.yul.o.radiomast.io/20b6f77f-2177-46a2-b461-437a84273d5f",
"WBUR": "https://fm909.wbur.org/wbur_www",
"WNYC": "https://fm939.wnyc.org/wnycfm",
"BBC4": "http://as-hls-ww-live.akamaized.net/pool_55057080/live/ww/bbc_radio_fourfm/bbc_radio_fourfm.isml/bbc_radio_fourfm-audio%3d96000.norewind.m3u8"
}
Once it’s there, you can add whatever you want to it, delete, change the URLs if you find a better one, etc.
Initially I was just running this on my laptop, but for scheduling recording, that meant I had to keep my laptop from sleeping. Eventually I got a bit of hardware to run it on. A tiny NUC - a mini computer. The one I got cost only $169 US. It’s about 6 inches square and a couple inches high. It’s very low powered. Came with Windows 11 which ran like a dog. But I wiped that and put Ubuntu Server on it and it’s great. I spent a bunch of time setting up that enviornment and getting it so I can securely ssh into it. I put tmux on it, so I can just open a tmux pane, schedule a few recordings, then detach from that session and it stays running on the server. The recordings then get SCP’ed over to my NAS where they appear in my Jellyfin server. Quite happy with this setup.
I’m pretty happy where this has wound up, but I have a few other things in mind.
Some shows might start a few seconds early or go a couple minutes late. I’ve been manually starting them to record at times such as 8:59 and setting the length to be a couple minutes longer. I’m thinking of making a setting that does that automatically.
I started looking into some overseas stations like the BBC and realized that the UK is not in the same time zone as the eastern US. Who knew!? Doing time-based math is not fun, so I may have to put a time zone in the recording parameter.
As mentioned in the start, this is all just a fancy wrapper around ffmpeg, so you need to have that installed. The play functionality uses ffplay, which should come with your ffmpeg install I think.