PVR Cron

For about a year now, I’ve been playing around with my digital tuner card. It wasn’t until I turned off the cable that I have a need to use it. Using some cool linux tools, I’ve made a script to record HDTV broadcasts to my computer. It is a work in progress, but here’s what I’ve got so far.

The Tuner Card
The tuner card is DVB based on a Conextant chipset, so the first step was to get my kernel to make the card usable. A quick check will show if the driver is loaded:

dmesg | grep dvb

The Tools Required

  • dvb-atsc-tools
  • azap
  • ffmpeg

Channel Scan
Scan for channels using:

dvbscan /usr/share/dvb/atsc/us-ATSC-center-frequencies-8VSB > ~/.azap/channels.conf

Edit the file ~/.azap/channels.conf to make sure the channel names are correct. Your base frequencies file may be in a different location, but it is usually under /usr/share.

Iteration 1: Crontab Recording
At first, I used only the crontab to record. Here’s an example:

24 12 * * * /usr/bin/azap -c /home/dvr/.azap/channels.conf -r WRDW-HD
25 12 * * * /bin/cat /dev/dvb/adapter0/dvr0 > /data/dvr/young-restless.mpeg
35 13 * * * /usr/bin/pkill cat
36 13 * * * /usr/bin/pkill azap
37 13 * * * /usr/bin/ffmpeg -i /data/dvr/young-restless.mpeg -s 1024x476 -vcodec libxvid -b 1600000 -acodec copy /data/dvr/y-r-friday.avi

This is a very ugly solution with lots of cracks. For instance, if I were running cat from a console when /usr/bin/pkill cat were running, it would die. Heaven forbid another processes is using cat when that runs. Also, I had to change the name of the ffmpeg output file every day.

Iteration 2: Cronable Perl Script
This script does pretty much the same thing as the above 4 lines in the crontab does. This means you don’t have to write 4 lines in the crontab for each recording, just 1 line. Also, the file name is appended with the date in yyyy-mm-dd format.


#Does someone need a reminder?
if ( $#ARGV != 2 ) {
print “Usage:\n”;
print “record.pl \n”;

#Creates a random 16 character (a-z) string
sub randstr {
my @chars=(‘a’..’z’);
my $res = “”;
for(my $i=0;$i<16;$i++) {
$res .= $chars[rand($#chars)];
return $res;

#Grab the command line args
my ( $channel, $length, $finalFileName ) = @ARGV;

#Temporary mpeg filename
my $tempFileName = randstr();

#Add date to final filename
$finalFileName .= “-“.`date +%Y-%m-%d`;
$finalFileName =~ s/\n//;

#Start Azap in the background
print “Starting azap\n”;
system( “/usr/bin/azap -c /home/barry/.azap/channels.conf -r $channel >/dev/null 2>/dev/null &” );
sleep 5;

#Start cat in the background
print “Starting cat\n”;
system( “/bin/cat /dev/dvb/adapter0/dvr0 > /data/dvr/$tempFileName.mpeg &” );

#Sleep the required seconds for the show to record
print “Recording for “.(60*$length).” seconds…\n”;
sleep 60*$length;

#TODO: Remove pkill, as it may cause problems
print “Killing cat and azap.\n”;
`pkill cat`;
`pkill azap`;

#Resize & Encode to XVID using ffmpeg
#ffmpeg sometimes stops working b/c of bad mpeg data
#TODO: Replace with mencoder
print “Encoding…\n”;
`/usr/bin/ffmpeg -i /data/dvr/$tempFileName.mpeg -s 1024×476 -vcodec libxvid -b 1600000 -acodec copy /data/dvr/$finalFileName.avi`;

#Remove the temporary mpeg file
`rm $tempFileName.mpeg`;

print “Done!\n”;

I know it’s not the most elegant of perl scripts, but it gets the job done. Here’s a sample cron:

25 12 * * * /home/dvr/record.pl WRDW-HD 70 young-restless

As you can see from the TODO comments, I continue to tinker with the script. When I make a good development, I’ll post it. If you have any suggestions, feel free to post a comment or contact me.