AppleTV – A quick TVML app

I’m playing with the new Apple TV SDK.  I’ve created a simple TVML “app” and server component, to allow viewers to watch the fifty most recent government programs from my hometown, Douglas, MA.

If you’re curious: Install the Xcode 7.1 beta.  Download the TVMLCatalog sample project from Apple.  Open the AppDelegate.swift file.  Change the line:

    static let TVBaseURL = “http://localhost:9001/”

to

    static let TVBaseURL = “http://www.douglasma.org/tvml/”

And run.  You should see something like this:

Screen Shot 2015 09 20 at 10 42 35 AM

Videos play as you’d expect.  Be prepared: We compress the heck out of these videos, so they’ll look crummy compared to anything you’ll usually see.  320×240 at a glorious 400Kbps.  A story for another day.

I can’t promise that URL will always be there or won’t change, although I’m guessing I’ll keep the URL the same as I improve the presentation.

The details on how I built this are after the jump…

As background: I Chair the Cable Committee here in Douglas, MA.  One of our responsibilities is recording all public meetings.  We play them on local Public Access TV, and also put them online for permanent archive.  Meeting metadata is stored in a MySQL database.  You can see the web version of this here.

In the sample project’s js/application.js I changed the reference to the main Index file, appending a “.php”.  So the line:

var index = resourceLoader.loadResource(`${options.BASEURL}templates/Index.xml.js`,

became

var index = resourceLoader.loadResource(`${options.BASEURL}templates/Index.xml.js.php`,

I renamed templates/Index.xml.js to Index.xml.js.php so I could include a little PHP code, to pull in my data.

I modified the Index.xml.js.php file to generate this:

var Template = function() { return `<?xml version="1.0" encoding="UTF-8" ?>
<document>
  <head>
    <style>
      .descriptionLayout {
        tv-text-max-lines: 8;
      }
    </style>
  </head>
  <listTemplate>
    <list>
      <header>
        <title>50 Most Recent Douglas Government Videos</title>
      </header>
      <section>

     <listItemLockup videoURL="http://streamingdl.douglastv.org/media/video/Octoberfest_2015_09_15.mov">
          <title>Octoberfest Committee: September 15, 2015</title>
          <relatedContent>
                  <lockup>
                     <img src="http://streamingdl.douglastv.org/media/video/Octoberfest_2015_09_15_conv.jpeg" />
                     <title>Octoberfest Committee: September 15, 2015</title>
                     <description>
The meeting length is approximately eighteen minutes.</description>
                  </lockup>
           </relatedContent>
      </listItemLockup>

      </section>
    </list>
  </listTemplate>
</document>`
}

I left some spaces around the program-specific content above, which repeats for each of the 50 items.  I pulled the program-specific stuff from the database, and repeat that block.

listItemLockup puts a list item on the right side of the screen.  The videoURL is passed to the playback code (more on that in a minute).  The relatedContent tag is the detail info shown on the left when this item is selected.

Then a quick edit to js/Presenter.js.  With all the template sample code, Apple didn’t think to include anything to actually play video.  Look for this block at line 109:

    load: function(event) {
        console.log(event);
        var self = this,
            ele = event.target,
            templateURL = ele.getAttribute("template"),
 presentation = ele.getAttribute("presentation");

Just afterwards, I added this bit of code to tell the Apple TV to play the video when selected:

videoURL = ele.getAttribute("videoURL")    
if(videoURL) {       
 var player = new Player();       
 var playlist = new Playlist();       
 var mediaItem = new MediaItem("video", videoURL);
 player.playlist = playlist;       
 player.playlist.push(mediaItem);       
 player.present();
}

(Thanks to the Ray Wenderlich site for that snippet!)

And that’s it.

’m lucky enough to have won the Apple TV developer lottery, and can confirm this runs great on the real thing.  When changing the Bundle Identifier I had to add the new App Transport Security stuff to the Info.plist to allow http access:

   <key>NSAppTransportSecurity</key>    
      <dict>        
      <key>NSAllowsArbitraryLoads</key>        
      <true/>    
   </dict>

(Yes, the exception should target the video server in question, but this is fine for testing.)

Enjoy!

 

Comments are closed.