I have a secret to confess. I own an iPad… You see, I decided to make the leap into the tablet world back in 2011 when Android tablets really hadn’t made their mark yet. I really wanted to get an Android tablet but none of them really even stood close to the iPad around that time. Plus I had a friend at work who had one so he let me try it out. Now, let me defend myself. When the first iPad was launched a little more than a year earlier, I laughed, so hard. I thought the iPad was the STUPIDEST thing Apple had come out with to date. How could anyone buy a $500 device that didn’t even support an external SD card?!?! However, I did end up buying one and I quickly realized why it became so popular.

I love me some MythTV. I LOVE watching video on my iPad. Could I combine the two to make (in my eyes) the perfect TV watching experience? Well I did, and I’m here to tell you how. My current solution does not cover live streaming channels. I don’t have enough free time to where I find myself even wanting to watch Live TV but one of these days I’ll try and get around to seeing if I can figure out how to do that anyways. Currently I have a script to automatically re-encode recordings to an “Apple friendly” format that, thanks to Cisco, works on Firefox and Chrome for the Linux desktop as well.

So I’ll start with the bash script I wrote and setup as a User Job in MythTV.

transcode_720p_for_ipad.sh #!/bin/bash # Arguments DIR=$1 FILE=$2 ENCODE=$3 KEEP=$4 JOBID=$5 # Basic input sanity check if [ $# != 5 ]; then echo "Usage: transcode_720p_for_iPad.sh (directory) (filename) (encode=[true/false]) (keep=[true/false]) (jobid)" else # Get the root filename (e.x. 1131_20120804070000) FILE_ROOT=`echo $FILE | sed 's/.mpg//'` echo "fileroot: $FILE_ROOT" # Main transcoding, uses HandBrakeCLI and the default iPad profile # using the --preset "iPad" option resulted in a really lousy encode, # pulled the CLI options from HandBrake website to vastly improve quality of transcode if [ $ENCODE = "true" ]; then echo "Transcoding: /usr/bin/HandBrakeCLI -i \"$DIR/$FILE\" -o \"$DIR/$FILE_ROOT.m4v\" -e x264 -q 20.0 -r 29.97 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -4 -X 1280 --loose-anamorphic -m" # iPad preset = -e x264 -q 20.0 -r 29.97 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -4 -X 1280 --loose-anamorphic -m # -m (chapter markers) # -X 1280 (max width 1280 px) # -4 (large file) # -e x264 (x264 encoder) # -q 20.0 (video quality slider) # -r 29.97 (framerate) # --pfr (video framerate control = peak-limiting frame rate control) # -a 1 (first audio track) # -E faac (faac audio encoder) # -B 160 (160 kbps audio rate) # -6 dpl2 (dolby prologic 2 mixdown) # -R Auto (auto audio sample rate) # -D 0.0 (dynamic range compression in decibels) # -f mp4 (mp4 file formate) (/usr/bin/HandBrakeCLI -i "$DIR/$FILE" -o "$DIR/$FILE_ROOT.m4v" -e x264 -q 20.0 -r 29.97 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -4 -X 1280 --loose-anamorphic -m 2>&1 ) > $DIR/transcode_720p_for_iPad_keep.log & MYPID=$! echo "PID $MYPID" sleep 30 MYSTATUSINFO=`cat $DIR/transcode_720p_for_iPad_keep.log | sed 's/\r/

/g' | tail -1` echo "My status: $MYSTATUSINFO" while [ "$MYSTATUSINFO" != "" ]; do MYSTATUSINFO=`echo $MYSTATUSINFO | sed 's/\r/

/g' | tail -1 | grep -E --only-matching '[0-9]{1,2}\.[0-9]{2}.*\)'` # update MYSQL library. mysql -umythtv -pmythtv mythconverg -e "update jobqueue set comment = '$MYSTATUSINFO' where id = $JOBID" ## test output echo $MYSTATUSINFO > $DIR/status.txt MYSTATUSINFO=`tail -1 $DIR/transcode_720p_for_iPad_keep.log` done echo "outside while loop" fi wait $MYPID # Rename png's from .mpg.xxx.png to .m4v.xxx.png if not already done so for testfile in $DIR/$FILE_ROOT*.png do if [ ! -f `echo $testfile | sed 's/\(.*\.\)mpg/\1m4v/'` ]; then mv $testfile `echo $testfile | sed 's/\(.*\.\)mpg/\1m4v/'` else echo "$testfile already exists, skipping." fi done BASENAME=$FILE_ROOT.m4v echo "basename: $BASENAME" FILESIZE=$(ls -l $DIR/$BASENAME | cut -d\ -f 5) echo "filesize: $FILESIZE" LASTMODIFIED=$(ls -l --time-style=full-iso $DIR/$BASENAME | cut -d\ -f 6,7 | sed 's/\.[0-9]*$//') echo "last modified: $LASTMODIFIED" mysql -umythtv -pmythtv mythconverg -e "update recorded set basename = '$BASENAME', lastmodified = '$LASTMODIFIED', transcoded = 1, filesize = $FILESIZE where basename = '$FILE' or basename = '$BASENAME'" # DEBUGGING STATUS # mysql -umythtv -pmythtv mythconverg -e "select basename,lastmodified,transcoded,filesize from recorded where basename = '$BASENAME'" if [ $KEEP = "false" ]; then rm $DIR/$FILE fi echo "done" fi

Save the script somewhere (I chose /usr/bin/transcode_720p_for_iPad.sh and mark it executable sudo chmod +x /usr/bin/transcode_720p_for_iPad.sh Go into mythtvbackend config, then General Settings, and add a User Job as follows.

User Job #1 description: Transcode 720p for iPad User Job #1 command: /usr/bin/transcode_720p_for_iPad.sh %DIR% %FILE% true false %JOBID%

If you want to keep the original *.mpg file for transcoding into an archival format just change the user job to /usr/bin/transcode_720p_for_iPad.sh %DIR% %FILE% true true %JOBID% The mpg file will be in your storage directory but unaccessable from mythweb. In order for this script to be able to write to your storage directory, you need to allow mythtv the ability to chown file in your storage directory. I save all my mythtv files to a separate hard drive mounted under /media/Scratch . Edit sudoers to allow mythtv to chown files.

sudo visudo

Edit the # User privilege specification section, add the following line at the end.

mythtv ALL=NOPASSWD: /bin/chown *\:* /media/[^..]*

Modify your recording schedules to automatically run your new user job upon completion of recording. You can transcode after the fact from mythweb by navigating to your recording and then executing the user job from mythweb.

Now let’s tie it all together with a little php, pearl and a dash of html. We’re going to need to modify three mythweb files, namely the detail.php, stream_raw.pl and the utils.php files. On Ubuntu these files are located in the following directories:

/usr/share/mythtv/mythweb/includes/utils.php /usr/share/mythtv/mythweb/modules/stream/stream_raw.pl /usr/share/mythtv/mythweb/modules/tv/tmpl/default/detail.php

Edit utils.php and edit the switch ($ext) { block to add case 'm4v' : return "$url.m4v"; at the end.

Edit stream_raw.pl and in the # File type section add the following elsif statement.

elsif ($basename =~ /\.m4v$/) { $type = 'video/mp4'; $suffix = '.m4v'; }

Finally, edit detail.php to add an HTML5 video player to your details page. Replace the entire

<div id="x-downloads"> </div>

structure. This

contains all the flashplayer crap that we don’t want or need. We will replace it with the following HTML5 video tag and div structur. <div id="x-downloads"> </dev> <video width="320" height="240" controls> <source src="<?php echo video_url($program, 'mpg') ?>" type="video/mp4"> Your browser does not support the video tag. </video> </div> You should now have a beautiful HTML5 video player!

