I like to listen to NPR when I work out but radio reception at my gym is horrible.  In order to resolve this problem I wanted to record NPR and download it onto my MP3 player.  Since I also travel a bit, I wanted to be able to access the recording on the road (I actually like finding local NPR stations, but sometimes I can’t get good reception).

If all you want to do is record a radio stream, this instructable is amazing, helpful, and all you really need.  If you want to go a bit nuts and go well beyond what’s necessary, here’s a more elaborate option.

Here are the steps I had in mind:

  • Record audio automatically
  • Edit out parts of the recording as needed
  • Transcode edited WAV recording into MP3
  • Make MP3 available anywhere with an internet connection
  • Automatically load edited MP3 onto MP3 player

Bonus challenge: I wanted to avoid making my (7+ year old) home laptop a core part of this setup because I didn’t want to have to keep it on all the time.  At one point I was using a local ubuntu server I had running all of the time to do some of it, but it was a pretty underpowered via epia rig (good from an electricity standpoint, bad from a performance standpoint).  That made the MP3 conversion slow.  As a result, I moved the recording, transcoding, and editing to the cloud for $5/month.

Outline of process:

  1. Initiate WAV recording on remote server
  2. Stop WAV recording on remote server
  3. Initiate WAV recording on remote server (I’ll explain this below)
  4. Stop WAV recording on the remote server
  5. Combine the two WAV files created in steps 1 and 2, 3 and 4, respectively
  6. Transcode the unified WAV file into a single MP3 file
  7. Download the MP3 file from the remote server to a local MP3 player
  8. Unmount the MP3 player

To put it it bit more simply - create the file on the remote server and then move it onto the local MP3 player.

What you will need (or at least what I used):

  • A cloud server running ubuntu (I used Digital Ocean because they had great documentation to walk me through a process I didn’t fully understand.  You could just do this with a local computer). $5/mo
  • A Raspberry Pi (although this is not necessary if you have a linux box that is always running - raspberry pi as the advantage of having a low enough energy requirement that I don’t feel bad running it all the time). $40
  • An MP3 player.  I use a sansa clip for working out because it is small, relatively cheap, gets FM radio reception, and much more sweatproof than my phone.  But anything that mounts as an external drive will work here. $40.

Step 1: Prepare the remote server

I’ve been running a local ubuntu server for long enough that I almost kind of know what I was doing.  Fortunately, the Digital Ocean’s documentation was fantastic and helped me though the complicated parts.

After setting up the cheapest ubuntu server available (this is an embarrassingly low impact use of a remote server) there were a few things that I made sure were working:

First, set up SSH keys for access.  This is more secure and allows my local computer to log in automatically.  Tutorial here.  Life is slightly easier if you have generated the public keys for all of the local computers (including the PI) you want to use to access the remote server ahead of time (the server setup will let you automatically include them) but only just.  It isn’t the end of the world if you do it after the server is set up.

Second, make sure your server automatically installs security updates.  The server is a computer and it needs updates just like any other computer, but I’m not fooling myself into thinking that I will ever remember to do this.  Tutorial here.

Third,  make sure lame, mplayer, and sox is installed on your server.

Step 2: Create some scripts

This section builds off of this amazing instructable from before.  As I mentioned above, I made this process a bit harder because I wanted to edit out about 10 minutes from the middle of the recording.  Why? Because it was a recurring segment that I didn’t really like and its my recording so I can do whatever I want.

Instead of recording everything and finding a way to automatically edit out the part I didn’t want, I decided it would be easier to record the first part, wait 10 minutes, and record the second part.  After that I pulled the two parts together and turned them from a (big) WAV file into a (small) mp3 file.  In order to do that, I needed to create 4 super small scripts.  (Note: there is probably a much more efficient way to do this).

streamrecord0 and streamrecord 1

These are identical programs, except for the fact that they name their output “mystream0.wav” and “mystream1.wav” respectively.  One is used to record the first chunk and one is used to record the second chunk.  The entirety of the scripts is below.  Just copy it into a text editor, save it, and make it executable (as described here.)

#!/bin/sh
NOW=$(date +“%b-%d-%y”)
mplayer “http://wamu.org/streams/live/1/live.pls” -ao pcm:file=/tmp/mystream0.wav -vc dummy -vo null ;

and

#!/bin/sh
NOW=$(date +“%b-%d-%y”)
mplayer “http://wamu.org/streams/live/1/live.pls” -ao pcm:file=/tmp/mystream0.wav -vc dummy -vo null ;

There is no line break in the line that starts with “mplayer."  Replace the URL with the URL of the stream you want to record (this can often be found by looking for a streaming option called "MP3” or “PLS” - here’s WAMU’s page as an example.  It WILL NOT just be the main website of the station).  /tmp/mystream0.wav is the name of the output file and can be changed to whatever you want (just make sure you change the other scripts accordingly, and that you name the outputs of the two files different things or the second one will just save over the first one).

pkill

This script stops the streamrecord script, thus “finalizing” the file. It probably doesn’t even need to be a script.

pkill mplayer

soxer

This script takes the two recorded files, combines them, and turns them into a single mp3 file.

#!/bin/sh
pkill mplayer;
sox /tmp/mystream0.wav /tmp/mystream1.wav /tmp/mystream2.wav;
lame /tmp/mystream2.wav /home/mystreamB.mp3;

The first line ends any recording that is happening.  The second line (the sox line) takes the two recordings (mystream0.wav and mystream1.wav) and turns them into a single recording  (mystream2.wav).  The third line (the lame line) takes the single recording (mystream2.wav) and turns it into an mp3 (mystreamB.mp3).  Change that final directory (just /home/ in the example above) to wherever you want the file to go.

Step 3: Schedule some scripts

Now you have some scripts, but they are just kind of hanging out.  They need to be scheduled to do us any good.  This is a job for cron.  Cron is a program that automatically runs scripts at scheduled intervals, which is exactly what you want to do.

Typing “crontab -e” in your command line will bring up the croneditor (there are also various programs that can guide you through the process).  My cron table looks like this:

30 4 * * * /scripts/streamrecord0
50 4 * * * /scripts/pkill
00 5 * * * /scripts/streamrecord1
30 6 * * * /scripts/soxer

The first number is minutes, the second is hours, and the next 3 are day of month, month, and week.  Since I want these to run every day, the last 3 are just *, which means “every time.”

As you can see, streamrecord0 (which lives in the /scripts/ directory) starts at 4:30am.  At 4:50am pkill stops it.  At 5:00am streamrecord1 starts.  At 6:30am soxer stops streamrecord1, merges streamrecord0 and streamrecord1, and turns the output into an mp3 (because that’s what is in the soxer script).  While everything else is pretty much instantaneous, transcoding almost two hours of WAV into mp3 takes about 3 minutes (which will vary by processor).  If you want to see how long your rig will take, just type “lame [combined wav file] [location and name of output file]” like you see in the soxer script into the command line and watch.

Congratulations!  Now you have the recording of your choice on a server far away.  It’s time to bring it home.

Step 4: Prepare your local computer (Raspberry Pi)

I explained why I am using a raspberry pi for this above, but you can use pretty much any computer that will be on when you need it for this.  If you are using a raspberry pi, set it up.  I followed adafruit’s guide, specifically steps 1, 2, 3, 6, and 7 (although 7 just made my life a bit easier and isn’t strictly required).  If you didn’t when you set up the original server, you will also need to add the pi’s public key (in ~/.ssh/id_rsa.pub) to the cloud server (in /root/.ssh/authorized_keys by default).

Step 5: Create script on local computer

This one is pretty easy.  Assuming you have ssh set up correctly, you can just pull the file off of the cloud server automatically.  I also added a line to my script that unmounts my mp3 player so I can just pull it off of the pi in the morning (this means that if I don’t use the mp3 player that day, I need to detach and reattach it before I go to bed so it is actually mounted when the script runs).

Create this script the same way as the others (and don’t forget to make it executable).  I called it “pipull” because it pulls the file for the pi.

#!/bin/sh

scp USERNAME@IPAaddressOfRemoteServer:/recordings/mystreamB.mp3 /media/0123-4567/PODCASTS/mystreamB.mp3;

umount /media/0123-4567;

in order for this to work for you, you need to replace “USERNAME” with your username for the remote server (hint: it is probably just “root”) and IPAaddressOfRemoteServer with, you know, the IP address of your remote server.  Also, if you changed the output  location of the mp3 you will need to change that part.

The /media/0123-4567/PODCASTS may be specific to your MP3 player as well.  Mine happens to mount at /media/0123-4567 and have a default directory of PODCASTS, but if yours does not you will need to make changes accordingly.

The scp part automatically transfers the mp3 from the server to your remote player (and overwrites any existing mp3 by the same name - like yesterday’s).  The umount unmounts the player.  Note: my MP3 player doesn’t recognize that the file is actually new and if I don’t tell it to play it from the beginning the file will begin playing where I ended the previous day. This can be slightly disorienting.

Step 6: Schedule your script

Just as with the server, the final step is to schedule your script to happen every day.  My crontab looks like this:

34 6 * * * home/pi/scripts/pipull

Note that it runs at 6:34am.  That gives the remote server time to turn the WAV file into an MP3 before downloading.

And that’s it!  One final note.  In order to make my mp3 player mount automatically (instead of having it pop up a dialogue box asking me if I wanted to mount it) on the pi, I opened the pi’s file manager (via VNC ) and went to edit -> preferences -> volume management.  There I checked “mount mountable volumes automatically” and “mount removable media automatically” and unchecked “show available options for removable media."  I don’t know if all of  those are strictly necessary, but they got the job done.

Keep 3D Printers Unlocked (the win! 2023)

Last summer I [submitted a request](https://michaelweinberg.org/blog/2023/07/13/1201-kickoff/) that the Copyright Office renew an existin...… Continue reading