The Alternative to Hacking

From AwkwardTV
Revision as of 06:24, 21 June 2010 by Simplicity (talk | contribs) (Automate Everything (Mac Only))
Jump to: navigation, search

Automate Everything (Mac Only)

Coming soon - how to make a folder that receives any video file, converts it to an Apple TV and iTunes friendly format, copies it to iTunes and processes it. --Simplicity 11:25, 21 June 2010 (UTC)

What we're going to do

Mac OS X has a standard feature called "Folder Action Scripts". The system will run an Applescript we'll create each time a file is added to the folder. This script will convert the video file to an iTunes friendly, Apple TV format. It will add it to iTunes and do some basic processing of it, too. Although this process uses Applescript, I will explain each part step-by-step, as this is meant to be a beginner's guide.

What we can't do: process HD videos and have them come out as HD videos. This is a limitation of Handbrake. HD videos some out as a middle ground - higher quality than SD, but not full HD.

Getting Started

A few little bits to do in advance. If you can't do any of these steps without further instruction, then this guide is a little too advanced for you. :-)

Download the latest Handbrake CLI version from here and place it in your home directory. Everything else you need is already installed.

Create a folder called "Automatic" in your home directory.

Create a playlist called "AutoAdded" in iTunes.

You can change the names and locations of any of the files / playlists above, but if you do, you need to suitably amend the steps / scripts outlined below.

The Script

First and foremost, hardcore Applescript users will simple fall over and die with horror at the mess that it the following script. I am self-taught and cobbled bits from all over the internet. I'm sorry about this. But, I can only say that this works for me and if anyone want to add spit and polish, they should go right ahead!

Open Applescript Editor (Applications --> Utilities). A blank script is in front of you. Add the following code. You can just copy and paste in.

Hack Me Not

For all cool things that you can do with your Apple TV without resorting to all that SSH malarkey or touching a screwdriver, read on. If you want to contact me, please do so though this site. --Simplicity 13:57, 4 June 2008 (CEST)

Stream and Sync Simplified

One of the very best reasons to hack your Apple TV was to get more storage. With 2.0 and iTunes 7.6.1 onwards you get much better sync / stream options. The ATV used to distinguish between "Shared" iTunes libaries, from which you could stream content and that which was synced. Now, you can select what to sync and what to stream from a library and as long as the iTunes Mac/PC is on, all the content is available seamlessly - whether local to the ATV or not.

Better still, you can choose what TV Shows to sync (Last 1,3,5+ or unwatched episodes only) of selected shows, so if the iTunes Mac/PC is off, you can still watch the latest episodes.

With this seamless sync / stream linking to your iTunes library, even a 40Gb ATV becomes totally usable.

More Content

Everything you can put on a hacked ATV, you can put on a normal ATV running 2.x. And, you won't have to pray that a new firmware release won't break everything. Only a one-time conversion of existing files is needed. Compared to the time you need to maintain a hacked ATV, it's really, genuinely, properly, not much hassle.

DVD Rips

Use the free Handbrake for all your DVD ripping needs. It has presets for the Apple TV, which will deliver near DVD quality rips that will stream easily to your ATV.

DivX / AVI

Previously, you could convert any AVI movies you had kicking around using the freely available iSquint or its shareware big brother VisualHub from Techspansion. Sadly though, both these brilliant programs were discontinued in late September, 2008.

Fortunately, the team behind HandBrake is picking up where Techspansion left off.

Easy Metadata

Whatever you have ripped or downloaded can be converted using the above and then copied to iTunes, but it will appear without any TV Show / Movie data like episide name, number, etc. To fix...


Make Video Tags is first choice as it has a basic but effective interface. With iTunes 8, this seems to be working more reliably than before. Alternatively, try the more hands on Set Video Kind of Selected. Both from Doug's AppleScripts for iTunes.

TVTaggr also looks like a promising project, with future versions possibly scraping the internet to auto-populate key fields.


Check out MetaX. Pretty easy to use and grabs data from the Internet.

Rentals / Podcasts / iTunes Store

Come here, there's more. Running 2.x, you get get movie rentals, buy TV shows and browse podcasts straight from your Apple TV. A lot of items in the store are now available in HD, too.

Not in the US and missing rentals and TV Shows? You can get a US Account by following the instructions posted here and buying US iTunes Gift Vouchers from Internet Tat Bazaar eBay.


If you have a Linux computer running the excellent video recording software VDR, you can extend VDR to be able to produce Apple TV compatible video files including metadata based on the information sent with the DVB EPG (albeit the type (movie or show) will be guessed). Here is a short HOWTO for setting it up. It is based on an Ubuntu Jaunty install using Hanno's e-tobi Debian VDR builds but should be adaptable to all other VDR installs as well. The following directions are for the computer running VDR, nothing has to be done on the Apple TV. The script will produce an Apple TV compatible, H.264 encoded MP4 file with AAC audio and put it in a defined directory. This can then be shared via Samba or NFS to be able to access it from Mac OS or Windows. Then, the only thing you have to do is drag and drop the generated MP4 files to iTunes and review the metadata.

But: It doesn't support cutlists. So, you have to cut the recording first and transcode the cut one.


  • VDR up and running
  • working FFMPEG with libx264 and libfaac support (For Ubuntu, consult this link on how to compile it the right way)
  • At least Java Runtime Environment 1.5 in your PATH, i.e., the user running VDR can launch the "java" command without explicitly specifying a path
  • The user running VDR must have a valid shell (i.e. not /bin/false, but /bin/bash or /bin/sh)
  • The command "at" working and accessible by the user VDR runs as

The FFMPEG preset

For H264 encoding, the FFMPEG authors recommend using presets. The following one produces quite good results at reasonable encoding speeds. Copy it to the folder containing the global (system-wide) presets (e.g. /usr/share/ffmpeg) as libx264-appletv_normal.ffpreset



Install Java (at least JRE 1.5) and get ProjectX 0.90.4 or higher. Place the ProjectX.jar file along with the whole lib folder in a directory the user running VDR has access to. Then, rename the ProjectX.jar to pX.jar or create a symlink.

Create a file named pX.ini in the same directory where you copied (or symlinked) the above ProjectX files and put the following content into it:

# Application
# ExternPanel
# WindowPosition


Install tcmplex-panteltje and make sure the command is in your PATH.

Atomic Parsley

To embed the metadata, Atomic Parsley is used. Either install it from your distribution's repository or from the link. Make sure it is invoked with AtomicParsley and resides somewhere in your PATH.

The script itself

Put the following script somewhere where the user running VDR has access to. Call it and make it executable for the user running VDR.


# VDR2ATV version 0.2
# This script is provided as-is, without any warranty. It is licensed under the GNU GPL v3.

# Please review the following variables and adjust the paths according to your configuration

# This directory indicates where to put the encoding queue.
# It has to be writable by the user VDR runs as

# Here the temporary audio and video files as well as the logs will go.
# The temporary files will be deleted after finishing a transcoding process
# but the logs will be kept.
# The user VDR runs as needs to have write permissions for this dir.
# This must be on a partition with enough free space on it. 10GB will do.

# This is the directory where the completed files will go.

# This is the path to your ProjectX dir.
# In this dir, the pX.jar, pX.ini and the libs for pX will be expected.

# The path to the SVDRPSEND command to send progress messages to the VDR OSD.

# The video dir (default for manual VDR installs is /video)

# If this word exists in the title or subtitle of the recording,
# a movie is assumed. Else, the script tries to guess the video type.

case "$1" in
    if [ -f $SPOOLDIR/queue ]; then
      for n in `cat $SPOOLDIR/queue`; do
        cutnum=`echo $dest |grep -o "/" |wc -l`
        cutnum=`expr 1 + $cutnum`
        suff=`echo $dest |cut -d/ -f$cutnum`;suff=`echo /$suff`
        i=`expr index $dest \/`
        if [ $i -eq 1 ]; then
        cutnum=`echo $dest |grep -o "/" |wc -l`
        cutnum=`expr 1 + $cutnum`
        file=`echo $dest |cut -d/ -f$cutnum`
        suff=`echo /$file`
        if [ `echo $file |grep -E ^%+.* |wc -l` -ge 1 ]; then
          file=`echo $file |sed 's/%//'`
        echo $file \(`du -m $n |sort -n |tail -n1 |awk '{print $1}'`MiB\)
      if [ `wc -l $SPOOLDIR/queue |awk '{print $1}'` -eq 0 ]; then
        echo Queue is empty!
      echo Queue is empty!
    if [ -f $SPOOLDIR/queue ]; then
      touch $SPOOLDIR/temp
      for n in `cat $SPOOLDIR/queue`; do
        if [ $n != $2 ]; then
          echo $n >>$SPOOLDIR/temp
      cp $SPOOLDIR/temp $SPOOLDIR/queue
      rm $SPOOLDIR/temp
      $0 l
      echo Queue is empty!
    rm $SPOOLDIR/queue
    touch $SPOOLDIR/queue
    echo Queue is now empty.
    found=`grep $2 $SPOOLDIR/queue |wc -l`
    if [ $found -lt 1 ]; then
      echo $2 >>$SPOOLDIR/queue
    $0 l
    if [ -f $SPOOLDIR/queue ]; then
      if [ -f $SPOOLDIR/worker ]; then
        echo There is already another job running!
        $SVDRPSEND MESG There is already a job running!
        $SVDRPSEND MESG Starting transcode job
        mv $SPOOLDIR/queue $SPOOLDIR/worker
        for n in `cat $SPOOLDIR/worker`; do
          $SVDRPSEND MESG Demultiplexing $n
          mkdir -pv $TEMPDIR
          dir=`mktemp -d -p $TEMPDIR`
          echo + $n
          echo + $dir
          mkdir -pv $dir
          cutnum=`echo $dest |grep -o "/" |wc -l`
          cutnum=`expr 1 + $cutnum`
          suff=`echo $dest |cut -d/ -f$cutnum`;suff=`echo /$suff`
          i=`expr index $dest \/`
          if [ $i -eq 1 ]; then
          cutnum=`echo $dest |grep -o "/" |wc -l`
          cutnum=`expr 1 + $cutnum`
          file=`echo $dest |cut -d/ -f$cutnum`
          suff=`echo /$file`
          if [ `echo $file |grep -E ^%+.* |wc -l` -ge 1 ]; then
            file=`echo $file |sed 's/%//'`
          $SVDRPSEND MESG Demultiplexing $file with ProjectX
          for m in `find "$n" -name ???.vdr |sort`; do
            echo \"$m\"
          done |xargs java -Djava.awt.headless=true -jar $PX/pX.jar -ini $PX/pX.ini -out $dir
          $SVDRPSEND MESG Remultiplexing with only the first audio track
          cd $dir
          tcmplex-panteltje -i 001.mpv -0 `ls ???.* |grep -v mpv |sort -n |head -n 1` -m s -o temp.mpg
          cd $CURDIR
          rm -rf $TEMPDIR/complete
          mkdir -pv $TEMPDIR/complete/$destdir
          $SVDRPSEND MESG Transcoding to H264/AAC
          ffmpeg -y -i $dir/temp.mpg -threads 8 -deinterlace -vcodec libx264 -vpre appletv_normal -b 1500k -bf 16 -acodec libfaac -ar 48000 -ab 128k $TEMPDIR/complete/$destdir/$file.mp4
	  $SVDRPSEND MESG Embedding metadata
	  for m in `find $TEMPDIR/complete -name *.mp4 `; do
	    info=`find $n -name info.vdr |head -n 1`
	    echo +++ $info
	    echo +++ $m
	    descr=`grep ^D $info |sed 's/D //'`
	    tit=`grep ^T $info |sed 's/T //'`
	    sub=`grep ^S $info |sed 's/S //'`
	    chan=`grep ^C $info |sed 's/C [SCT][-0123456789]* //'`
	    contains_film=`echo $tit $sub |grep -i $MOVIETRIGGER |wc -l`
	    has_subtitle=`grep ^S $info |wc -l`
	    if [ $contains_film -eq 0 ]; then
	      if [ $has_subtitle -gt 0 ]; then
	        echo +++ is show
	    echo +++ $isshow $contains_film $has_subtitle
	    if [ $isshow -eq 1 ]; then
	      if [ `echo $tit |grep -e / |wc -l` -gt 0  ]; then
                epnum=`echo $tit |cut -d/ -f1 |sed 's/[^0123456789]//g'`
                numeps=`echo $tit |cut -d/ -f2 |cut -d\  -f1 |sed 's/[^0123456789]//g'`
                tit=`echo $tit |sed 's/[^\/]*\/[^\/ ]*\ //'`
	      elif [ `echo $sub |grep -e / |wc -l` -gt 0 ]; then
                epnum=`echo $sub |cut -d/ -f1 |sed 's/[^0123456789]//g'`
                numeps=`echo $sub |cut -d/ -f2 |cut -d\  -f1 |sed 's/[^0123456789]//g'`
                sub=`echo $sub |sed 's/[^\/]*\/[^\/ ]*\ //'`
              if [ $epnum -ge 0 ]; then
                echo +++ AtomicParsley $m --stik "TV Show" --title "$sub" --tracknum "$epnum/$numeps" --TVEpisodeNum "$epnum" --TVShowName "$tit" --description "$descr" --TVNetwork "$chan"
              	AtomicParsley $m --stik "TV Show" --title "$sub" --tracknum "$epnum/$numeps" --TVEpisodeNum "$epnum" --TVShowName "$tit" --description "$descr" --TVNetwork "$chan"
                echo +++ AtomicParsley $m --stik "TV Show" --title "$sub" --TVShowName "$tit" --description "$descr" --TVNetwork "$chan"
                AtomicParsley $m --stik "TV Show" --title "$sub" --TVShowName "$tit" --description "$descr" --TVNetwork "$chan"
	      if [ $has_subtitle -gt 0 ]; then
	        echo +++ AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit - $sub"
	        AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit - $sub"
	        echo +++ AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit"
	        AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit"
	  temp1=`find $TEMPDIR/complete -name *-temp*.mp4 |head -n1`
	  temp2=`find $TEMPDIR/complete -name *.mp4 |sort |head -n1`
	  cp -v $temp1 $temp2
	  rm -v $temp1
          $SVDRPSEND MESG Copying files to outdir
          mkdir -pv $OUTDIR
          cp -Rvf $TEMPDIR/complete/* $OUTDIR/
	  chmod -Rvf 777 $OUTDIR
          $SVDRPSEND MESG Deleting temporary files
          rm -Rvf $dir
          rm -Rvf $TEMPDIR/complete
        rm $SPOOLDIR/worker
      echo Queue is empty!
    if [ `wc -l $SPOOLDIR/queue |awk '{print $1}'` -lt 1 ]; then
      echo Queue is empty!
      LOGFILE=$TEMPDIR/atv-`date +%Y%m%d%H%M%S`.log
      echo $0 t \>$LOGFILE 2\>\&1 |at now
    echo This script has to be called from within VDR.

Create the directory the variable SPOOLDIR points to and make it writable for the user VDR runs as. Then make the script executable.


Put the following into your reccmds.conf or if using a VDR distro which builds this file automatically on each start, put it into the custom reccmds file:

Apple TV : true
- Transcode this : /etc/vdr/vdr2atv/ a
- Don't transcode this : /etc/vdr/vdr2atv/ d
- Clear queue : /etc/vdr/vdr2atv/ x
- Show queue : /etc/vdr/vdr2atv/ l
- Start transcoding : /etc/vdr/vdr2atv/ start

Replace /etc/vdr/vdr2atv/ with the real path to where you put it.


Now, when selecting a recording and pressing "Red" in the VDR menu, a new entry named "Apple TV" will show up. Selecting it will open up a submenu where you can queue and un-queue the selected item, convert everything on the queue or clear/show it.

Log files will be created as atv-<current date>.log in the temporary folder, if anything goes wrong.

The script is not much more than a "quick and dirty hack" and has plenty of optimization potential.