Sync Podcasts in Linux
I enjoy a good podcast when I'm completing my daily administration tasks. I
also have a 4GB MuVo2 (see Figure 1) that I reserve space on for podcasts
when I travel. But I downloaded shows manually, and I added and removed
shows by hand as well. As a Linux user, this was unacceptable. I needed a
way to automatically download and sync podcasts with my player. Nothing
fancy - I didn't even need a GUI. And I certainly didn't want to use a
closed-source solution. So I chose to create my own solution with Linux and
Open Source software.

Figure 1: Creative 4GB MuVo2
I started out with a list of podcast feeds and put them in a text file,
/etc/feeds. I noted that I wanted the ability to comment out any shows that
I didn't have the time or space to listen to.
# /etc/feeds
# Hacker Public Radio
http://www.hackerpublicradio.org/hpr_rss.php
# The Linux Link Tech Show
#http://www.thelinuxlink.net/tllts/tllts.rss
# Mac Break Weekly
http://leoville.tv/podcasts/mbw.xml
# The Metpod
http://metropolis.co.jp/podcast/rss/
#Newsreal
http://files.becomethemedia.net/rss/rantmedia/newsreal/24k/
# Off the Hook/Wall
http://www.2600.com/rss.xml
# Security Now!
#http://leoville.tv/podcasts/sn.xml
# TWiT
http://leoville.tv/podcasts/twit.xml
Next, I wrote a Perl script that would iterate through that list, grab the
RSS XML with LWP, parse it with a regex for the enclosure tag, and then
download each MP3 with wget. It downloaded the latest podcast from each
feed, and I added the capability to download every MP3 from a feed by adding
the 'all' tag after the URL. I used no clobber with wget to avoid extraneous
bandwidth use.
#!/usr/bin/perl -w
# podgrab.pl -
use strict;
use LWP::UserAgent;
# Get the podcast addresses from a file
open my $feeds, '<', "/etc/feeds" or die ">>> Can't open feeds: $!";
# Read the podcast URLs and pass
# them to the download function
while (<$feeds>) { download($_) unless /^#|^\s+$/; }
# Begin download function
sub download {
# Check for and set the all flag
my $all;
chomp(my $url = $_[0]);
if ($url =~ s/\s+all$//) { $all = 1; }
else { $all = 0; }
# Grab the content and check status
my $browser = LWP::UserAgent->new();
my $cast = $browser->get($url);
my $stat = $cast->status_line;
print "$stat\n\n" unless $cast->is_success;
# Read in cast content
my $content = $cast->content;
# Grab the latest or every enclosure,
# if it doesn't/they don't exist
while ($content =~ /<enclosure.+url="(.+\.mp3)/g) {
system("wget -nc $1");
last unless $all == 1;
}
# End download
}
That was a good start, but I still had to automate syncing. So, I wrote a
bash script that called podgrab and rsync to add new podcasts to the MuVo,
and remove podcasts that I deleted from my computer. I used xmessage to
signal success or failure (see Figure 2).
#!/bin/bash
# podload.sh -
# Local workstation
LOCAL="$HOME/media/podcasts"
# Portable media player
PRTBL="/media/MUVO^2"
if [ -d $PRTBL ]; then
cd $LOCAL
./podgrab
sleep 1
(rsync -av --delete $LOCAL/ $PRTBL/podcasts && \
xmessage -center "Podcasts synced!" &> /dev/null) || \
xmessage -center "Sync failed!" &> /dev/null
else
xmessage -center "$PRTBL not mounted!" &> /dev/null
fi

Figure 2: xmessage
I could change the local and portable directories as needed, and remove
xmessage altogether if I worked without a GUI. My problems were solved. No
more surfing around to multiple sites for my audio fix, and no more dealing
with two sets of shows. All thanks to Linux and Open Source.
Other Resources
Meizu M6 Mini Player
TWiT Netcast Network
