So there’s this webcast you really want to hear to but can’t because of work, or you’re gonna be out of town, or any one of many of life’s little conflicts that prevent you from physically being in front of the computer when the show airs. Wouldn’t it be nice if there was some kind of audio equivalent of TiVO that would let you record the show so that you could listen when you wanted, when it was convenient to you?
Well, it won’t search for similar content, and you have to know the url of the webcast, but aside from that, we can automate the recording of daily webcasts with MPlayer and Cron.
Why use MPlayer?
Well for one, MPlayer can play almost any file format. Since we’re concerned with streaming audio, however, we’re only going to have to deal with, primarily, three formats: MP3, Real Audio and Windows Media. Optionally, you may run across an Ogg stream that you want to grab but, since it requires only a minor change to the script I’m going to explain to you, I’ll save it’s explanation for later.
Secondly, MPlayer has the ability to allow you to specify which audio-out plugin you want to use with a command line switch (-ao). If you were using the Enlightenment audio server, you could tell MPlayer to use the -ao esd switch. If you were using KDE, you could tell MPlayer to use the Arts sound server with the -ao arts switch. If you want to see all of the audio out options compiled with your version of MPlayer, I suggest you type mplayer -ao help from the command line, trust me, it’s output will come up again later.
Finally, MPlayer is a command line client. Sure, you can make it use a graphical front-end but it’s command line functionality makes it very easy to implement in shell scripts.
So, what now?
What we want to do is save the audio to a disk file. Remeber when I suggested you see which plugins were compiled in with MPlayer? If you had checked, you would have seen a line like this:
pcm RAW PCM/WAVE file writer audio output
This audio-out switch instructs MPlayer not to play the stream to the standard audio device but instead to send the stream to a wav file on your hard drive. In essence, the pcm plugin let’s you record streams to disk.
So, let’s test this out. Go to Shoutcast and find a radio station you want to record. Right-click and save the link to disk. Rename the resultant file to playlist.txt, it’ll be something like shoutcast-playlist.pls?rn=4219&file=filename.pls. You can rename it whatever you want to call it. If it’s an 80’s stream, name it eighties.txt or FlockofSeagulls.txt, it really doesn’t matter what you call it as it’s just a text file and mplayer doesn’t really care about the file extension anyway.
Now, open up a terminal and type mplayer -playlist playlist.txt -ao pcm -aofile mystream.wav -vc dummy -vo null
You should see a stream of text that looks something like the following:
Connecting to server 64.236.34.97[64.236.34.97]:80 ... Name : CLUB 977 The 80s Channel (HIGH BANDWIDTH) Genre : 80s Pop Rock Website: hTtP://club977.com/ads Public : yes Bitrate: 128kbit/s Cache size set to 1024 KBytes Connected to server: 64.236.34.97 Cache fill: 18.75% (196608 bytes) Audio file detected. ========================================================================== Opening audio decoder: [mp3lib] MPEG layer-2, layer-3 MP3lib: init layer2&3 finished, tables done AUDIO: 44100 Hz, 2 ch, 16 bit (0x10), ratio: 16000->176400 (128.0 kbit) Selected audio codec: [mp3] afm:mp3lib (mp3lib MPEG layer-2, layer-3) ========================================================================== Checking audio filter chain for 44100Hz/2ch/16bit -> 44100Hz/2ch/16bit... AF_pre: af format: 2 bps, 2 ch, 44100 hz, little endian signed int AF_pre: 44100Hz 2ch Signed 16-bit (Little-Endian) alsa-init: requested format: 44100 Hz, 2 channels, Signed 16-bit (Little-Endian) alsa-init: 1 soundcard found, using: hw:0,0 alsa1x: 44100 Hz/2 channels/4 bpf/65536 bytes buffer/Signed 16 bit Little Endian AO: [alsa1x] 44100Hz 2ch Signed 16-bit (Little-Endian) (2 bps) Building audio filter chain for 44100Hz/2ch/16bit -> 44100Hz/2ch/16bit... Video: no video Starting playback... A: 3.0 2.3% 25%
Now open another terminal window and type ls. You should see the file mystream.wav in the file listing. If you were to type du mystream.wav every so often, you’d see that the filesize is increasing and you’re actually recording the stream. Neat isn’t it. Use MPlayer to listen to the wav and verify that it’s recording what you want.
What’s the deal with the playlist flag?
If you’ve been to this site before, you may notice the -playlist switch that was talked about in the MPlayer playlist, and Cron-MP3 Alarm Clock articles. In order to understand why you need the playlist switch when playing streaming audio, you need to understand a bit more about how streaming audio works.
Each streaming format has a kind of playlist file that your music player uses to redirect it to the actual music stream. For Windows Media it’s .asf, for Real Audio it’s .ram, MP3 uses .m3u and .pls. Even though each format has it’s own unique file extension, each file is basically the same. They’re just text files with urls pointing to the actual streams. Take your editor and open the playlist.txt file and see for yourself. If you see one of those file extensions, you’ll need to download the playlist and use the -playlist switch to play/record those streams.
Ogg, however, is an exception. Most Ogg streams, such as those from Icecast servers, don’t require the -playlist switch because the server handles all of the redirection without the need for a playlist. Those Ogg streams that do require the switch are usually just a static directory full of oggs. In such an event, the static directory versions usually implement a playlist file and use the same file extensions as MP3.
In theory, the -playlist switch doesn’t require the playlist file to reside on your hard drive. You should be able to just type mplayer -playlist http://full/url/to/playlist.pls and it should work. However, I’ve had mixed results with that method. Downloading the playlist to hard drive has worked for me every time. Feel free to experiment using the URL instead of the downloaded file, as your results may differ from mine.
What about the other options?
The -ao switch has an option to allow you to specify what you want the resultant wav file to be called. MPlayer defaults the filename to test.wav but, using the -aofile switch, you can specify what you want the file to be called, and where you want the file to be saved. This is pretty handy for scripts, which we’ll see in a moment. Additionally, since we’re primarily concerned with audio, the -vc dummy and -vo null switches tell MPlayer that we don’t care about any video content. This will result in a performance increase while we’re writing the stream to file.
Writing the script
Now that we have a basic understanding about what’s going on, and we’ve seleceted a stream we want to record on a regular basis, we’re going to write the script to take care of it for us. In theory, if you write a lot of scripts for your own use, it’s a good idea to create a directory for them and add it to your $PATH. Let’s create a directory named scripts (mkdir scripts), pretty unoriginal, I know, but it gets the job done. Now move your playlist.txt into the script directory (mv playlist.txt scripts), then cd into the scripts directory and fire up your text editor of choice (try vim, it’s crunchy).
#!/bin/sh
mplayer -playlist /home/username/scripts/playlist.txt -ao pcm -aofile /tmp/mystream.wav -vc dummy -vo null ;
oggenc /tmp/mystream.wav -o /home/username/FlockofSeagulls_date +%b%d.ogg ;
rm /tmp/mystream.wav ;
Copy and paste the above into your editor and save it as streamrecorder. Now make the file executable (chmod 700 streamrecorder) and type from the commandline streamrecorder.
This will create a wav file in the /tmp directory (make sure it’s writable). Whenever you tell MPlayer to quit recording (ctrl-c or killall -9 mplayer), oggenc converts the wav file, deposits an ogg file in your home directory named FlockofSeagulls_May20.ogg and, then the rm command removes mystream.wav to save disk space. You may want to omit the rm command until you’ve tested the script a few times. If the server you’re downloading your stream from flakes and drops the connection, MPlayer will exit and you won’t get the entire program.
The tickmarks around the date appends the current date to the filename but preceds the file extension. Just a nice little extra to help you visually sort out which days what files were recorded and it keeps you from overwriting your file every time the script runs. If you want more help setting the date more to your liking consult the date MAN page.
Optionally, if you would prefer your output in MP3 format, and you have the lame package installed, replace oggenc /tmp/mystream.wav -o /home/username/FlockofSeagulls_ with the following line:date +%b+%d.ogg ;
lame -m s /tmp/mystream.wav -o /home/username/FlockofSeagulls_.date +%b%d.mp3
The stream I want to record is already in the format I want
This simplifies things a bit. If the stream you want to record is already in the format you want to use, you can use the -dumpstream flag instead. Your streamrecorder script will look like this instead:
#!/bin/sh
mplayer -playlist /home/username/scripts/playlist.txt -dumpstream -dumpfile /home/username/FlockofSeagulls_date +%b%d -vc dummy -vo null ;
This will result in a file called FlockofSeagulls_May20, without a file extension, in username’s home directory. This eliminates the intermediate temporary file and the encoding step. You can add the extension after just like in the previous script if you want. It doesn’t matter as MPlayer doesn’t require the extensions in order to play the file but your desktop environment may like the extensions in order to associate the file with whichever media player you’d prefer when you click it in your file browser.date +%b%d
Putting it all together
Now that we’ve written our script, let’s set up a Cron script to automate the process for us. From a terminal, type crontab -e to bring up the crontab editor. If you used the Cron-MP3 alarm clock tutorial, your crontab file probably looks something like this:
20 6 * * 1-5 /home/username/alarm >& /dev/null
We’re going to add a couple of new entries to start and stop our stream recorder. We want to record our program Monday through Friday, from 11A.M. to 2P.M. so our new crontab will look like this:
20 6 * * 1-5 /home/username/scripts/alarm >& /dev/null
0 11 * * 1-5 /home/username/scripts/streamrecorder >& /dev/null
0 14 * * 1-5 killall -9 mplayer
If you’re wondering why we’ve appended >& /dev/null read Suppressing Crontab Emails. Once you’ve saved out your crontab, you’re all set. You can forget about making sure you’re glued to your computer to catch your favorite webast and, instead, listen at your own leisure.
Posted by Philip McClure in Linux on May 20, 2004