Using the ideas behind declan's blog post, I recently created
unofficial podcasts for two of my favorite WPTF radio talk shows: Neal Boortz (a Libertarian,
author of The
FairTax Book) and Bill Handel (a true master of sarcasm,
delivered in the context of legal advice to
callers-in). Though I listen to the radio quite a bit during the day,
those shows come
on at inconvenient times. Truly, a technological solution could assist here, and
declan's blog
got me almost all the way there. Though his taste in radio
obviously differs quite a bit from my own, our needs were
the same in this regard.
🙂
radioShark, complete with terror-inducing fin. Soundtrack optional.
Here's an overview, for those impatient. I use a radioShark to schedule an automatic recording of
the shows I am interested in. I wrote a Perl script which runs after the
recordings finish that converts them into AAC
files (with an m4b extension, to support bookmarking on an iPod) using
a Nero
encoder and sends them via FTP to my web server. A specific URL on my web site invokes
a PHP script which scans the directory for those files and creates an on-the-fly RSS
XML document. Then, using iTunes or whatever software you may prefer, you can
register that URL to download new
episodes as you feel the need.
Ready to see how it's done? Good. Let's go.
[more below]
Step one: Obtain radioShark
I got mine on amazon,
where you can buy a new one for $45, or a used one for about $35.
The software that came with the radioShark was
quite outdated; there were much
newer, more functional versions available on the official radioShark download page.
Step two: Set up your recordings
Use the radioShark software to
schedule automatic recordings of the shows you
are interested in. In my case, I knew that the shows started about
5-6 minutes
after the hour (after a news break), so I took this into account; for the first
hour of Neal Boortz, I
started recording at 8:05pm and recorded for 55 minutes.
(Note: experimentation has shown that the show actually
begins at about 8:06pm, so
I might adjust this accordingly.) Neal's show broadcasts for two hours on
WPTF, so I
set up two recordings, one from 8:05pm-9:00pm, and another from
9:00pm-10:00pm. I did similar trickery for Bill
Handel's show. Remember to set your
programs up to recur on the appropriate days.
radioShark recording schedule. Note the separate
recordings for each
hour of programming, to skip news
breaks
The radioShark lets
you decide how to encode your recordings, and I chose to
save them as raw WAV files. These are quite large
(I believe around 550 MB per hour), but the purist in me wouldn't
let me encode them to MP3 just to re-encode
them later. (It probably would be fine
to do that so as to save massive amounts of disk space, since I'm going
to
use a high-compression encoding later, and let's not forget that it's already AM radio quality!
I'm just weird that way, and I couldn't bring myself
to do it. Ahh well, disk space is cheap.)

settings for recording one hour of
programming
In your radioShark settings, note the directory
where your captured audio will
be stored, as we'll process files in that directory using our encoding and
upload
script.
At this point, your radioShark should be spamming your hard drive with massive
meggage of unencoded
audio on a regular basis. This cannot be, so we must
proceed to…
Step three: Encode and upload
Now, we must create encoded AAC files from our currently massive, unencoded WAV
audio.
In his blog, declan used the free FAAC encoder, but,
despite my repeated efforts, I could not get the results I
wanted; iTunes always complained that the audio
files were corrupted. I am most certain that it is
something I was doing wrong, despite the fact that I used the
exact same syntax
as he, but after much research and many failed attempts, I went with something
else: BeSweet v1.5 (beta) using the Nero DLL's.
Note that Nero is a commercial product, and so
you must have a license in
order to use this method. I did have such a license, so it was a good fit for me. If
you
don't have a license, I can only advise you to either get one (Nero is
an excellent product, that's why I
have a license) or try something else.
Download version 1.5 of BeSweet (this version is still in
beta, at the time of
this writing) and install it on your machine. Then, as it says in this (confusing) page, copy
aacenc32.dll, aac.dll, and NeroIPP.dll from your Common
Files/Ahead/AudioPlugins folder, into your BeSweet
installation directory.
Now, you have a functioning encoder. We just need to set it up to run on the
audio
files generated by the radioShark. I do this via a Perl script which I set
to run every evening at 10:15pm, when all
of the day's recordings should have
completed. It scans the directory where the radioShark's recordings
live,
encodes anything it finds, uploads the result to my web server via FTP, and then
cleans up.

radioShark recordings; these huge files are
generated automatically by radioShark
You likely don't
have Perl on your Windows machine, so you'll have to grab ActivePerl (which is free) and install it. This will
give you the ability to run the
encoding/upload script.
All that being said, here's my script:
use Net::FTP;
use Time::localtime;
$filepath = "C:/Public/RadioSharkRecordings/";
$besweet = "C:/BeSweet/BeSweet.exe";
$ftp_host = "####";
$ftp_user = "####";
$ftp_pw = "####";
@file_prefixes = ('Neal Boortz', 'Bill Handel');
# Add path prefix and ".wav" suffix to each, then concatenate the prefixes into a single string for "glob()"
$prefix_string = join " ", (map "${filepath}${_}*.wav", @file_prefixes);
# Now look for filename matches
while (defined($infile = glob($prefix_string))) {
print "Processing file $infilen";
# Parse the filename to extract the info it contains
if ($infile =~ /^.*[\/](.*)_(www)_(dd)_(dd)_(dd)_(dd).wav/i) {
($show_name, $day_of_week, $month, $day_of_month, $hour, $minute) = ($1, $2, $3, $4, $5, $6);
$year = localtime->year() + 1900;
$aacfile = "$filepath$year-$month-$day_of_month $show_name.m4b";
print "$besweet -core( -input "$infile" -output "$aacfile" ) -bsn( -vbr_tape -aacprofile_lc )";
system("$besweet -core( -input "$infile" -output "$aacfile" ) -bsn( -vbr_tape -aacprofile_lc )");
print "Connecting via FTP to $ftp_hostn";
$ftp = Net::FTP->new($ftp_host);
$ftp->login($ftp_user, $ftp_pw);
$ftp->binary();
print "Sending $aacfilen";
$ftp->put($aacfile);
print "Closing FTP connectionn";
$ftp->quit();
print "FTP transfer finishedn";
print "Deleting $infilen";
unlink $infile;
print "Deleting $aacfilen";
unlink $aacfile;
print "DONE WITH $infilen";
}
} # while loop for one prefix
You'll note that the configuration information (location of BeSweet,
location of your recordings) is up at the
top for convenience. There's also a
list (@file_prefixes) that specifies the show names that should be
processed. The
script looks for recordings with the specified show names in the format used by
the radioShark
recording system. Note that, for the converted filename ($aacfile)
I switch up the format a bit, using an ISO
standard date format which also makes
the encoded files sort properly.
On the BeSweet command line, I
specify a variable bit rate encoding, using the
"tape quality" preset. Though this is a relatively low
bit-rate
encoding, it shrinks it down nicely from 550 MB to 20 MB, and the quality has been
completely adequate for
my crazy AM radio needs. Note that I also specify an
extension of .m4b, which indicates to iTunes that the file is
an audiobook, so
bookmarking is enabled.
As this is a Windows machine, I set it up a Scheduled Task in the
Control
Panel to run this script every day.
Awesome. At this point, the radioShark is recording our shows,
and a Perl
script is converting t them to AAC format and uploading them to the webserver. Can
life get any better? I
submit that it can, if we only proceed to…
Step four: Generate
the RSS XML
Now, a directory on your web server is expanding at a good clip (~20 MB/recorded
hour),
although not as quickly as the directory on your hard drive was before.
So, how do we present them as a podcast?
We give iTunes a URL that resolves to an XML document in RSS format, with
attachments for the recorded
audio. That's all a podcast is. iTunes will connect
using HTTP to download everything. So, all we have to do is
generate that XML in
a web page at a URL that iTunes can access, and we're home free. Sounds like
an excellent
task for PHP.
Behold the set of scripts that I authored to do just this task.
I wanted separate
feeds for Neal Boortz and Bill Handel, so I needed to write
everything in a way that would allow me to have only one
copy of most of the
code. I did this by writing two very small scripts, one for my Neal Boortz
recordings:
<?php
require("podcast_base.php");
create_podcast_feed (
"Unofficial Neal Boortz Podcast",
"http://podcasts.drjason.com",
"*Neal Boortz*"
);
?>
…and a separate one for my Bill Handel recordings:
<?php
require("podcast_base.php");
create_podcast_feed (
"Unofficial Bill Handel Podcast",
"http://podcasts.drjason.com",
"*Bill Handel*"
);
?>
Both of these scripts use a function defined in
podcast_base.php, as follows:
<?php
function create_podcast_feed ($title, $url, $pattern) {
header("Content-type: application/xml");
echo "<?xml version="1.0" encoding="UTF-8"?>n";
?>
<rss xmlns:itunes="http://example.com/DTDs/Podcast-1.0.dtd" version="2.0">
<channel>
<title><?php echo $title; ?></title>
<link><?php echo $url; ?></link>
<?php
$files = glob($pattern);
$aacfiles = array();
if (is_array ($files)) {
foreach ($files as $file) {
$modtime = date("YmdHis", filemtime($file));
$aacfiles[$modtime] = $file;
}
krsort ($aacfiles);
foreach ($aacfiles as $aacfile) {
if (preg_match("/^(dddd)-(dd)-(dd) (.*).(m4.)/i", $aacfile, $backrefs)) {
$year = $backrefs[1];
$month = $backrefs[2];
$day_of_month = $backrefs[3];
$show_name = $backrefs[4];
$extension = $backrefs[5];
$file_url = $url . "/" . rawurlencode($aacfile);
?>
<item>
<title><?php echo "$show_name $month/$day_of_month/$year"; ?></title>
<enclosure url="<?php echo "$file_url"; ?>" type="audio/x-<?php echo "$extension"; ?>"/>
<guid><?php echo "$file_url"; ?></guid>
<pubdate><?php echo date("r", filemtime($aacfile)); ?></pubdate>
</item>
<?php
} // preg_match
} // foreach
} // if (is_array ($files))
?>
</channel>
</rss>
<?php
}
?>
As you can see, both of the small scripts pass in a
pattern, and the function
uses the PHP glob function to get a list of files that match that pattern. It
grabs the
modification time for each of the files and puts it all into a hash from
modification time (key) to filename
(value). I use the PHP krsort to sort the
hash by key, with newer dates at the top. Then, I iterate through the list
and
dump out the XML. Easy.

Podcast RSS XML in
FireFox
Any-hoo, I just dropped those scripts into the
directory with the AAC-encoded
audio files, and magic happens when I call them up on my browser.
Step five: Bathe in self-adulation
Now, it should all work. Just
enter the URL for one of the small scripts as a
manual podcast in iTunes, and you're golden.