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.

ssh: Remember each host’s settings

ssh: Remember each host’s settings

When you start using ssh to connect to other linux-based computers, you’re probably only going to a handful of machines. Easy enough to remember the username and hostname, but this won’t do when you’re working on 5 or more servers, especially if some offer ssh on a non-default port.

~/.ssh/config

In this file, you can set all the options for each host, including the username, host or ip, port, even which key to use. Here’s an example:

#Contents of $HOME/.ssh/config
Host dev
HostName 192.168.0.1
User dev-deploy
Port 2222
IdentityFile ~/.ssh/id_rsa.deploy.key

Host prod
HostName www.example.com
User prod555deploy
Port 5899

Host www.example.com
User admin123
Port 5899

It’s that easy! To use this config information, simply ssh:

ssh prod

Happy Computing!

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.

X11 Forwarding

A few days, I moved my desktop computer out into the living room. The computer has a tuner card that can receive digital broadcasts. I don’t own a TV, so this is the closest I’ve got to one. I still have to set up lircd before I can use a remote, but I wanted something a bit easier

Today, I discovered a new trick … SSH X11 Forwarding. Now, I can play video on my desktop right from my netbook. It’s wonderful and very simple!

In the following instructions, the “A” refers to the computer playing the video and “B” refers to any other computer.

  1. Make sure “X11Forwarding Yes” is in your sshd_config file on computer A. Restart sshd if you had to uncomment/add it.
  2. On B, run `ssh -XC A`
  3. In the ssh session, type `DISPLAY=:0.0`.
  4. Now run mplayer or any other video player in the  ssh session and it will play on computer A.

If you want  to have a program run on computer A and use the screen on computer B, the process is very similar:

  1. Make sure “X11Forwarding Yes” is in your sshd_config file on computer A. Restart sshd if you had to uncomment/add it.
  2. On B, run `xhost A`
  3. On B, run `ssh -XC A`
  4. Now run mplayer or any other video player in the  ssh session and it will play on computer A.

Step 2 authorizes use of the current display by computer A and only needs to be run once. Also, note that the display variable doesn’t need to be set when using B‘s screen.

Mplayer works wonderfully when playing on my desktop, plus I control it via the ssh session. It has tons of keyboard shortcuts. The ones I use the most are space for pause and the arrow keys for skipping around.

PVR Update

In anticipation of TV shows coming back on, I’ve been tweaking my PVR scripts. These record shows from the digital airwaves right onto my computer. I’ve separated the script into two parts: recording and encoding. Each is a simple one line shell script that can be called easily from the command line or from a cron. The record.sh script is:

/usr/bin/mencoder dvb://$1 -ovc copy -oac copy -o "$2.mpeg" -endpos $3

All this does is copy the video and audio streams directly to the disk. The three parameters are  the station name, as stated in ~/.mplayer/channels.conf, the filename and the end position. This end position can be the number or seconds to record, or a time format of hh:mm:ss. This makes recording fairly simple within the cron.

The encode.sh script contains:

/usr/bin/mencoder -vf scale=640:-2 -ovc xvid -xvidencopts bitrate=1700:threads=2 \
 -oac copy "$1" -o "$1.avi"

This, slightly more complex use of mencoder, will scale the video to 640 wide, the height calculated to keep the aspect ratio. The video is encoded into xvid at 1700kbps using 2 threads. To speed up the encoding process, the audio is not re-encoded, but copied as is.

You will need to play with the number of xvid threads to find the best fps. I have a dual-core and it encodes the fastest with 2 threads. It does need to be an integer, and most dual-cores will work best at 2.

Then, two lines are required in the cron to record and encode the program:

59 19 * * 1 /dvr/record.sh WAGTNBC /dvr/shows/heroes 01:03:00
05 20 * * 1 /dvr/encode.sh /dvr/shows/heroes.mpeg

Mencoder Cheat Sheet

Mencoder is a video encoder for linux. It is part of the mplayer package which also includes a video player. This tool is quite versatile and can do pretty much any kind of video processing all from the console.

As with any linux tool, there a tons of bells and whistles. This makes the learning curve kind of steep, but with a bit of determination anyone can make sense of it. Without further ado, here’s the cheat sheet:

mencoder clip1.avi clip2.avi -ovc copy -oac copy -o new-clip.aviCopies clip1 and clip2 into new-clip.avi
mencoder clip.avi -ovc xvid -xvidencopts bitrate=800  -oac lamemp3 -lameopts cb:br=128 -o new-clip.aviEncodes a clip with the xvid codec at 800Kbps and mp3 audio at 128Kbps.
mencoder clip.avi -ovc xvid -xvidencopts bitrate=800:threads=2  -oac lamemp3 -lameopts cbr:br=128 -o new-clip.aviSame as above, but uses 2 threads for the xvid encoding.
mencoder clip.avi -endpos 00:05:00 -ovc copy -oac copy -o new-clip.aviCopies the first 5 minutes from clip.avi into new-clip.avi
mencoder clip.avi -endpos 00:05:00 -ss 00:01:00 -ovc copy -oac copy -o new-clip.aviCopies 5 minutes from clip.avi into new-clip.avi, skipping the first minute.
mencoder dvb://WJBF-DT -endpos 01:0000 -ovc copy -oac copy -o ugly.betty.mpegTunes to WJBF-DT, records 1 hour of that station to ugly.betty.mpeg
mencoder clip.avi -vf scale=640:-2 -ovc xvid -xvidencopts bitrate=1200:threads=2 -oac copy -o new-clip.aviResizes the video to 640 wide, keeping the aspect ration, then encoding video using xvid at 1200Kbps and copying the audio directly
mencoder tv:// -tv driver=v4l2:width=640:height=480:device=/dev/video0 -ovc lavc -o >(tee webcam-`date +%Y-%m-%d-%H.%M.%S`.avi | mplayer -cache 128)Records the webcam to “webcam-yyyy-dd-mm-hh.mm.ss.avi”, where that is the date, and display it to the screen while recording.
mencoder -idx clip.avi -ovc copy -oac copy new-clip.aviFixes the AVI index of clip.avi, the output being new-clip.avi
mencoder clip.avi -vf cropdetect -o /dev/nullDetects what cropping is needed
mencoder clip.avi -of mpeg -mpegopts format=dvd -lavcopts vcodec=mpeg2video:vbitrate=5000:acodec=ac3 -o dvd-clip.mpegEncodes clip.avi into a dvd-compatible mpeg at 5000Kbps
mencoder -dvd 2 -ovc lavc -lavcopts vcodec=mpeg4 -oac copy -o dvd.aviRips a DVD to dvd.avi

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.

Cron Jobs

Cron jobs are the Linux/UNIX world’s scheduler. Many people, myself included, have a hard time understanding crons. After all, setting one up is very simple, if you know what you are doing.

The Crontab
crontab” is the utility you use to setup a cron job. Type “crontab -e” from the command prompt to edit your list of crons. It’s just a textfile with a special format. Each non-blank line is a cron job. The format of each line is 6 space separated fields. Here is what each field defines:

  1. Minute
  2. Hour (Military Time)
  3. Day of the Month
  4. Month
  5. Day of the Week (0 is Sunday, 1 is Monday, etc.)
  6. Program to run w/any arguments (may include spaces)

The Date/Time fields may be a specific number, a “*” meaning anything, a “*/x” meaning every x hours/minutes/etc., or a comma separated list of any or all of the above.

So, if you wanted a certain program to run every 30 minutes, you could say it any of these ways:

*/30 * * * * /path/to/program arg1 arg2
0,30 * * * * /path/to/program arg1 arg2
12,42 * * * * /path/to/program arg1 arg2

Use Absolute Paths
If you are writing a script to run as a cron, you must make sure your script uses full paths or it will throw an error. Yes, the script will execute without error when run from the command line, but the cron will crap out.

Examples

0 2 1 * * /home/apache/rotate-logs.sh

Runs the rotate-logs.sh script the first of every month at 2AM.

0 17 * * * /home/oddjob/send-margarita-time-email.sh

Runs the send-margarita-time-email.sh script at 5PM every day.

0 17 * * 1,2,3,4,5 /home/oddjob/send-margarita-time-email.sh

Runs the send-margarita-time-email.sh script at 5PM Monday – Friday.

0 4 * * 1 /usr/sbin/mysql_dump > /backup/mysql/backup-`date "+%Y-%m-%d"`

Performs a weekly backup of the mysql database Mondays at 4AM.

0 0 1,15 * * /home/accounting/payroll.pl

Runs payroll.pl on the first and fifteenth of every month at 12 midnight.

Points to remember

  • Use full paths in scripts
  • The crontab is only for the current user

Vim quick start

Vim is a open source text editor.  I fell in love with it a few years ago.  It runs on Linux, Windows, Macs, and others.  The interface is pretty much the same across the board. It really is full-featured.  It highlights almost any file syntax from PHP to python to httpd.conf.

One major barriers to its popularity is its learning curve.  Vim was designed to be used entirely by a keyboard.  To start, download it and install it.  If you’re running linux, it should be preinstalled.  Once it is installed, run it by running vi. When you run it, you can only scroll.

Press the i key or the insert key to go to insert mode and you can type all day long. Press the escape key to exit insert mode.

You can do a quick search by pressing forward slash and typing your search. To repeat the last search press the foward slash then enter.

All the other basic commands start with a colon.  Here are a few to get you started:

  • :w — write the file
  • :sav filename — save the file to filename
  • :q — quit
  • :n — go to the next file
  • :N — go the the previous file
  • :wq — write the file and quit
  • :q! — quit now!
  • :wn — write the file andd go to the next file

There is a key difference between “:q” and “:q!”.  The first will not quit if the file has been changed or there are more files to edit.  The second will quit immediately.

There are  a ton more features than what is listed here.  When you are ready to continue learning vim, type :help for a help screen.  Type :q to exit the help.

Happy editing.