Record Streaming Audio with Linux: Part II
March 3rd, 2006I said I was looking into getting FIFOs working so that the filesize requirements would be reduced. It's also more efficient this way. I was heavily influenced by the two scripts created by Daniel Howard.
So here's how it works. You get to create two scripts. The first one is for recording. It's an all-purpose script that I called record.sh. Here is the code:
-
#!/bin/bash
-
#
-
# record.sh
-
#
-
# Use mplayer to capture the stream
-
# at $STREAM to the file $FILE
-
#
-
# example: record.sh my_radio_show 60 mms://someserver.com/stream
-
-
DIR=/home/shawn/PodCasts #directory where to save the file
-
TEMPDIR=/tmp
-
-
# Don't edit anything below this line
-
#######################################################
-
DATE=`date +%d-%b-%Y` # Save the date as DD-Mmm-YYYY
-
YEAR=`date +%Y` # Save just the year as YYYY
-
NAME=$1
-
DURATION=$2 # enough to catch the show, plus a bit
-
STREAM=$3
-
TEMPFILE=$TEMPDIR/$NAME-$DATE
-
FILE=$DIR/$NAME-$DATE # Where to save it
-
-
# Capture Stream
-
mkfifo $TEMPFILE.wav
-
mkfifo $TEMPFILE-silenced.wav
-
-
# The lame settings below are optimized for voice encoding
-
# The sox command below strips out any silent portions
-
lame -S -a -m m --ty "$YEAR" --vbr-new -V 9 --lowpass 13.4 --athaa-sensitivity 1 \
-
--resample 32 $TEMPFILE-silenced.wav $FILE.mp3>/dev/null &
-
sox $TEMPFILE.wav -c 1 $TEMPFILE-silenced.wav \
-
silence 1 0.2 0.5% -1 0.2 0.5%>/dev/null&
-
/usr/bin/mplayer -quiet -cache 500 \
-
-ao pcm:file="$TEMPFILE.wav" -vc dummy -vo null \
-
-noframedrop $STREAM>/dev/null&
-
-
sleep 5
-
# get the pid of all processes started in this script.
-
PIDS=`ps auxww | grep $TEMPFILE | awk '{print $2}'`
-
-
# the & turns the capture into a background job
-
sleep `echo ${DURATION}*60 | bc` # wait for the show to be over
-
kill $PIDS # kill the stream capture
-
rm $TEMPFILE.wav
-
rm $TEMPFILE-silenced.wav
This script takes three args:
- the name of the show you're recording. This will be used in the final filename with the current date appended.
- the length of the show in minutes
- the URI of the stream (often
mms://orhttp://)
This integrates very well with another script that will hold all the data for the shows we want to record and automatically set the start times for us. Here is my script that I called today.sh
-
#!/bin/sh
-
#
-
# today.sh -- schedule what programs you want to rip today using the
-
# recorder script.
-
-
# Non-obvious paths
-
RECORDER=$HOME/bin/record.sh
-
RECORDER_HI=$HOME/bin/record-hi.sh
-
-
# Set up stations
-
KFI="http://a814.l1977144512.c19771.g.lm.akamaistream.net/D/814/19771/v0001/reflector:44512?MSWMExt=.asf"
-
WXNT=mms://wmc1.liquidviewer.net/WXNT
-
WPGB="http://84.53.144.36:80/D/1046/20063/v0001/reflector:43803?MSWMExt=.asf"
-
KOZZ=mms://lotusradio-kozz.wm.llnwd.net/lotusradio_kozz
-
-
# What day is it?
-
TODAY=`date +%a`
-
-
# EVERY DAY
-
#everyday() {}
-
-
# WEEKDAYS
-
weekday() {
-
# "Record John_Ziegler for three hours, starting at 7:00pm."
-
echo $RECORDER John_Ziegler 180 $KFI | at 7:00pm
-
echo $RECORDER Glenn_Beck 180 $WPGB | at 6:00am
-
}
-
-
# MONDAY
-
if [ $TODAY = "Mon" ]; then
-
# everyday
-
weekday
-
fi
-
-
# TUESDAY
-
if [ $TODAY = "Tue" ]; then
-
# everyday
-
weekday
-
fi
-
-
# WEDNESDAY
-
if [ $TODAY = "Wed" ]; then
-
# everyday
-
weekday
-
fi
-
-
# THURSDAY
-
if [ $TODAY = "Thu" ]; then
-
# everyday
-
weekday
-
fi
-
-
# FRIDAY
-
if [ $TODAY = "Fri" ]; then
-
# everyday
-
weekday
-
fi
-
-
# SATURDAY
-
if [ $TODAY = "Sat" ]; then
-
# everyday
-
echo $RECORDER Handel_On_The_Law 300 $KFI | at 6:00am
-
echo $RECORDER Dr_Dean_Edell 60 $KFI | at 2:00pm
-
fi
-
-
# SUNDAY
-
if [ $TODAY = "Sun" ]; then
-
# everyday
-
echo $RECORDER Jesus_Christ_Show 180 $KFI | at 6:00am
-
echo $RECORDER Glenn_Beck 180 $WPGB | at 10:00am
-
echo $RECORDER_HI Dr_Demento 120 $KOZZ | at 10:00pm
-
fi
Using this as a template you might notice another script being referred to. record.sh has audio processing optimized for talk radio. For higher quality and stereo, you need to change a few things. You can download all of the scripts mentioned here at the bottom of this post.
To finish off this solution you need to run today.sh at some point after 12:00am and before the start of the earliest program you wish to record. I set mine to run daily at 1:00am.
-
# Schedule recordings for today from radio streams
-
0 1 * * * /home/shawn/bin/today.sh>& /dev/null
Downloads:


March 3rd, 2006 at 11:06 am
SWEET! My prior work has been recycled and improved upon! :)
:) :) :)
Thanks,
-danny
March 3rd, 2006 at 11:10 am
[...] check out the comments that follow for tips and tricks, especially Shawn Dowler who has gone and wrote a page about his revised versions of thescripts. [...]
March 3rd, 2006 at 11:15 am
I was working on my own solution, but I knew it was lacking some things, so when I found your implementation I was very impressed. I especially liked the way you killed all the processes. That was what I was looking for when I found your scripts. Your scripts were great, so I merged what I had with what you had done and I'm very pleased with the results.
I especially like your today script. It is so much nicer than what I was doing before. Now I have a central human-readable place to keep all the program scheduling data outside of my crontab.
May 10th, 2006 at 5:37 am
Beautiful! Easy to understand the code, easy to implement, very useful results. Just what every Linux user dreams of. Thank you and congrats!
February 3rd, 2007 at 9:51 am
Thanks for this solution the scheduling of online programs was one of the items causing me to dual boot. Now I have one less reason to keep my XP partition. I just wish that it did not take me 5 days to find this solution after I started looking for it on the net! Again THANK YOU and also to all the authors of the pages that were referenced.
The only problem I am having getting this to work in Ubuntu is with RECORD_HI, but RECORD works great. I will figure that our soon enough, but this was a great start.
February 3rd, 2007 at 11:24 pm
@Michael Brehm:
I'm glad that I could help you find a way to solve your problems using Free Software. I love to hear stories like yours, and the thanks are always appreciated!
March 18th, 2007 at 3:48 pm
Your script is great, I'm trying to implement now, but I have a question as to why you are running lame, then sox, and finally mplayer. I'm sure this is correct, I am just wondering why?
Again, your script is tight, good work :-)
mxwlpxwl
March 19th, 2007 at 3:08 pm
@mxwlpxwl:
The sox command was a late addition as I noticed some of the stations were including long periods of silence in place of certain commercials. It doesn't happen as much anymore, but it still happens every now and again. The sox command just strips out silence, nothing more. You could leave it out, but it doesn't change much if you leave it in, so I just put it in for all of them.
I'm glad you like the scripts. Remember, I didn't come up with the concept, I just improved upon the original design.
August 6th, 2008 at 1:01 am
Hi,
how can I add a simple frontend which permits to insert:
1) the location where to save the stream
2) the url
2) the recording time
Moreover I would like to be able to start and stop the recording using a record and a stop button.
I've done in the past a simple gui using perl, but I don't know how to modify the script in order to stop the registration using the gui
August 8th, 2008 at 7:27 am
Hi,
I've done the following script which acts as a "wizard" with some pop up that enables the user to pass the input to the recorder.
Do you like it?
Do you think is it possible to modify it in order to pause the recording?
Thank you,
Xwang
August 8th, 2008 at 5:47 pm
Quite honestly, I don't know how you would accomplish pausing the recording. It's streaming live, so you certainly can't stop that part, but it may be possible to divert the stream through the fifos to
/dev/nullwhen a button is pressed and go back again afterward.I honestly don't have the "code fu" to do anything like that or to answer your question without a lot of fiddling and researching. I'm glad that you find the code useful, and I do appreciate your posting here with updates when you make interesting modifications.