Playing Video Files on Your TV with minidlna

Playing Video Files on Your TV with minidlna

One of my presents from Christmas a few years back was a Sony smart blu-ray player. It was marketed as something that easily streams files from your computer. That is absolutely true for anyone that runs Windows, just point and click. With Ubuntu, it’s a bit more complicated. Enter minidlna.

Installation

First thing, install minidlna. Open a terminal (Ctrl-Alt-t) and type this in:

sudo apt-get install minidlna

If you’d rather use the package manager, just search for minidlna.

Setup

The configuration file is editable by running this in the terminal:

sudo gedit /etc/minidlna.conf

There are 2 settings to note: media_dir and friendly_name. The names used are pretty explanatory. Here’s an example of what to update:

# Path to the directory you want scanned for media files.
media_dir=/path/to/shared/media

# Name that the DLNA server presents to clients.
friendly_name=fileserver

Save and close the file. On the terminal run this to refresh minidlna:

sudo service minidlna restart

That’s it! minidlna is all setup to server the files and folders in your media_dir.

XFS PVR/DVR maintenance

Last year, I purchased an HDTV tuner card and started using my computer as a Personal Video Recorder, or PVR. Basically, a small program records a tv show to the hard drive. This did quite well until March when it would stop recording after 5 seconds to 15 minutes for no apparent reason.

After about a month of research, I had ruled out just about everything under the sun. Then, it hit me … the file system might need defraging. The file system I am using is XFS, and they can get fragmented over time, especially if you have big files (HD-MPEGs) and little free space.

The command to defrag all mounted (and keeps them read-write) XFS filesystems is:

xfs_fsr -v

After running this, shows started recording better, but still stopped. So, I wanted to see just how fragmented everything was. I found this command:

xfs_db -r /dev/sda3

That starts an interactive XFS debug session for sda3, my XFS partition. Three useful commands are freesp, frag and quit. frag reported over 15% fragmentation and freesp reported a lot of small blocks and very few large blocks.

Finally, I got to the heart of the matter: defrag programs do not operate efficiently with less than a certain amount of free space. My drive had 20GB free out of 250GB total. I deleted a few HD shows to bring it up to 45GB free and ran the defrag command again.

Voila! Less than 6% fragmentation and plenty of free big blocks. My recordings are almost flawless now. At least they don’t stop for no reason. So, if you’ve got an XFS file system:

  • make sure to run the xfs_fsr command regularly
  • if you’re filesystem is still fragmented, burn/remove some junk and repeat

HDTV using MPlayer

In my desktop computer, I’ve got an nvidia GeForce 6150 PCI-E video card. It has a built-in mpeg2 decoding helper in it. Using Linux, this is called XvMC, or Xvideo Motion Compensation. I finally got it partially usable.

I’m currently watching the news on WJBF, the only channel I get b/c I haven’t fully setup my antenna. Using xvmc is fairly simple:

mplayer -vc ffmpegmc12 -vo xvmc -framedrop dvb://WJBF-DT

I add -framedrop to keep the video and audio sync’ed.  Mplayer will rant about waiting for retrace. Using OpenGL is actually better, for me at least.

mplayer -vo gl2 -framedrop dvb://WJBF-DT

It dropped 14 frames at the beginning, but hasn’t dropped another in 10 minutes. XvMC would have crapped out by now. A/V sync is still perfect. I’ve even got it full screen and it’s resizing from 1280×720 (720 HD resolution) to 1440×900.

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.


#!/usr/bin/perl

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

#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.