The Alternative to Hacking

From AwkwardTV

Jump to: navigation, search

Contents

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

TV

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.

Movies

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.

VDR

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.

Prerequisites

  • 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

coder=1
flags=+loop
cmp=+chroma
partitions=+parti8x8+parti4x4+partp8x8+partb8x8
me_method=hex
subq=6
me_range=16
g=250
keyint_min=25
sc_threshold=40
i_qfactor=0.71
b_strategy=1
qcomp=0.6
qmin=10
qmax=51
qdiff=4
bf=3
refs=2
directpred=3
trellis=0
flags2=+wpred-dct8x8+fastpskip

ProjectX

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
Application.Agreement=1
Application.Language=en
# ExternPanel
#ExternPanel.renameAudio=1
ExternPanel.renameVideo=1
# WindowPosition
WindowPosition.Main.Height=652
WindowPosition.Main.Width=906
WindowPosition.Main.X=50
WindowPosition.Main.Y=50

TCMPLEX

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 vdr2atv.sh and make it executable for the user running VDR.

#/!bin/bash

# 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
SPOOLDIR=/var/spool/vdr2atv

# 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.
TEMPDIR=/var/lib/video.00/atvtmp

# This is the directory where the completed files will go.
OUTDIR=/media/AppleTVExport

# This is the path to your ProjectX dir.
# In this dir, the pX.jar, pX.ini and the libs for pX will be expected.
PX=/etc/vdr/vdr2atv/pX

# The path to the SVDRPSEND command to send progress messages to the VDR OSD.
SVDRPSEND=/usr/lib/vdr/svdrpsend.pl

# The video dir (default for manual VDR installs is /video)
VPREFIX=/var/lib/video.00

# 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.
MOVIETRIGGER=movie

case "$1" in
  l)
    if [ -f $SPOOLDIR/queue ]; then
      for n in `cat $SPOOLDIR/queue`; do
        dest=${n#$VPREFIX}
        cutnum=`echo $dest |grep -o "/" |wc -l`
        cutnum=`expr 1 + $cutnum`
        suff=`echo $dest |cut -d/ -f$cutnum`;suff=`echo /$suff`
        dest=${dest%$suff}
        i=`expr index $dest \/`
        if [ $i -eq 1 ]; then
          dest=${dest#\/}
        fi
        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/%//'`
        fi
        destdir=${dest%$suff}
        echo $file \(`du -m $n |sort -n |tail -n1 |awk '{print $1}'`MiB\)
      done
      if [ `wc -l $SPOOLDIR/queue |awk '{print $1}'` -eq 0 ]; then
        echo Queue is empty!
      fi
    else
      echo Queue is empty!
    fi
    ;;
  d)
    if [ -f $SPOOLDIR/queue ]; then
      touch $SPOOLDIR/temp
      for n in `cat $SPOOLDIR/queue`; do
        if [ $n != $2 ]; then
          echo $n >>$SPOOLDIR/temp
        fi
      done
      cp $SPOOLDIR/temp $SPOOLDIR/queue
      rm $SPOOLDIR/temp
      $0 l
    else
      echo Queue is empty!
    fi
    ;;
  x)
    rm $SPOOLDIR/queue
    touch $SPOOLDIR/queue
    echo Queue is now empty.
    ;;
  a)
    found=`grep $2 $SPOOLDIR/queue |wc -l`
    if [ $found -lt 1 ]; then
      echo $2 >>$SPOOLDIR/queue
    fi
    $0 l
    ;;
  t)
    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!
      else
        $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
          dest=${n#$VPREFIX}
          cutnum=`echo $dest |grep -o "/" |wc -l`
          cutnum=`expr 1 + $cutnum`
          suff=`echo $dest |cut -d/ -f$cutnum`;suff=`echo /$suff`
          dest=${dest%$suff}
          i=`expr index $dest \/`
          if [ $i -eq 1 ]; then
            dest=${dest#\/}
          fi
          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/%//'`
          fi
          destdir=${dest%$suff}                                                                                                                          
          $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
          CURDIR=`pwd`
          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`
	    isshow=0
	    if [ $contains_film -eq 0 ]; then
	      if [ $has_subtitle -gt 0 ]; then
	        isshow=1
	        echo +++ is show
	      fi
	    fi
	    echo +++ $isshow $contains_film $has_subtitle
	    epnum=-1
	    numeps=0
	    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/[^\/]*\/[^\/ ]*\ //'`
              fi
              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"
              else
                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"
              fi
	    else
	      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"
	      else
	        echo +++ AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit"
	        AtomicParsley $m --stik "Movie" --description "$descr" --TVNetwork "$chan" --title "$tit"
	      fi
	    fi
	  done
	  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
        done
        rm $SPOOLDIR/worker
      fi
    else
      echo Queue is empty!
    fi
    ;;
  start)
    if [ `wc -l $SPOOLDIR/queue |awk '{print $1}'` -lt 1 ]; then
      echo Queue is empty!
    else
      LOGFILE=$TEMPDIR/atv-`date +%Y%m%d%H%M%S`.log
      echo $0 t \>$LOGFILE 2\>\&1 |at now
    fi
    ;;
  *)
    echo This script has to be called from within VDR.
    ;;
esac

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

reccmds.conf

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/vdr2atv.sh a
- Don't transcode this : /etc/vdr/vdr2atv/vdr2atv.sh d
- Clear queue : /etc/vdr/vdr2atv/vdr2atv.sh x
- Show queue : /etc/vdr/vdr2atv/vdr2atv.sh l
- Start transcoding : /etc/vdr/vdr2atv/vdr2atv.sh start

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

Results

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.

Personal tools