Guides and Sample Code

Developer

TVML Programming Guide

On This Page

Incorporating Multimedia in Your TVML App

TVML apps lend themselves to playing audio and video on an Apple TV. Using the client-server architecture, you can quickly load and stream a video.

Playing Background Audio

To incorporate background audio into your TVML app, add the background element to your TVML file. Inside of the background element, insert an audio element that contains an asset link to the music file. No changes to your TVMLKit JS file are required. Listing 8-1 shows the code required to put background music in your TVML app.

Listing 8-1Background music example
  1. <background>
  2. <audio>
  3. <asset src="URL to music file" />
  4. </audio
  5. </background>

The background music is tied to the visibility of the page. When a new page is pushed on to the stack or the current page is removed, the background music stops. However, if the new page also presents background music, using the same URL will continue to play the music without interruption.

Playing Multimedia in Your App

Play music or video in a TVML template app with TVMLKit JS. Listing 8-2 shows the code to create a template app that just plays a video. It creates a new MediaItem object and assigns the type of media and a URL. The media item is pushed on to a new Playlist object. The code then creates a new Player object, associates the play list and begins playing.

Listing 8-2Single video example
  1. App.onLaunch = function(options) {
  2. var singleVideo = new MediaItem('video', '*/Enter URL to video here');
  3. var videoList = new Playlist();
  4. videoList.push(singleVideo)
  5. var myPlayer = new Player();
  6. myPlayer.playlist = videoList;
  7. myPlayer.play();
  8. }
  9. App.onExit = function() {
  10. console.log('App finished');
  11. }

The above example creates an app that plays a single video—there is no need for a TVML file. However, there is no requirement that a play list only contains a single video. A play list can contain any combination of music and video items. The appropriate player is automatically presented depending on the type of media item being played.

Most TVML apps will play videos stored on their server and accessed from a TVML file. Listing 8-3 modifies the example used for page navigation to play audio and video. A new function, playMedia(extension, mediaType) is added to the file. This function takes two parameters, extension and mediaType. extension contains the path to the media file and mediaType contains the type of media to be played.

Listing 8-3AudioVideo.js example
  1. var baseURL;
  2. function loadingTemplate() {
  3. var template = '<document><loadingTemplate><activityIndicator><text>Loading</text></activityIndicator></loadingTemplate></document>';
  4. var templateParser = new DOMParser();
  5. var parsedTemplate = templateParser.parseFromString(template, "application/xml");
  6. navigationDocument.pushDocument(parsedTemplate);
  7. }
  8. function getDocument(extension) {
  9. var templateXHR = new XMLHttpRequest();
  10. var url = baseURL + extension;
  11. loadingTemplate();
  12. templateXHR.responseType = "document";
  13. templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML);}, false);
  14. templateXHR.open("GET", url, true);
  15. templateXHR.send();
  16. }
  17. function pushPage(document) {
  18. var currentDoc = getActiveDocument();
  19. if (currentDoc.getElementsByTagName("loadingTemplate").item(0) == null) {
  20. console.log("no loading");
  21. navigationDocument.pushDocument(document);
  22. } else {
  23. navigationDocument.replaceDocument(document, currentDoc);
  24. console.log("loading");
  25. }
  26. }
  27. function playMedia(extension, mediaType) {
  28. var videourl = baseURL + extension;
  29. var singleVideo = new MediaItem(mediaType, videourl);
  30. var videoList = new Playlist();
  31. videoList.push(singleVideo);
  32. var myPlayer = new Player();
  33. myPlayer.playlist = videoList;
  34. myPlayer.play();
  35. }
  36. App.onLaunch = function(options) {
  37. baseURL = options.BASEURL;
  38. var extension = "templates/mediaItems.xml";
  39. getDocument(extension);
  40. }
  41. App.onExit = function() {
  42. console.log("exited");
  43. }

The above example calls a TVML file that consists of a stackTemplate. The template contains displays two media items. When a media item is selected, the path to the file and the type of file are passed to the playMedia function. Listing 8-4 shows the code for the stack template.

Listing 8-4MediaItems.xml example
  1. <document>
  2. <stackTemplate>
  3. <banner>
  4. <title>Available Action Movies</title>
  5. </banner>
  6. <collectionList>
  7. <shelf>
  8. <section>
  9. <lockup onselect="playMedia('path to video', 'video')">
  10. <img src="path to image" width="182" height="274"/>
  11. <title>Movie 1</title>
  12. </lockup>
  13. <lockup onselect="playMedia('path to video', 'video')">
  14. <img src="path to image" width="182" height="274" />
  15. <title>Movie 2</title>
  16. </lockup>
  17. </section>
  18. </shelf>
  19. </collectionList>
  20. </stackTemplate>
  21. </document>

Figure 8-1 shows the stack template with two items, that when selected, cause the video player to begin playing.

Figure 8-1MediaItems.xml example output image: ../Art/mediaItems_2x.png

Adding an Overlay to a Video

You can overlay any TVML document on top of a video; however, it is recommended that you use divTemplate. Overlays provide the ability to present extra information to the user. You can display information like a URL to your website, company logo, or a phone number for users to call. There are two caveats when adding an overlay:

  • The overlay template must be loaded before assigning it to the Player object. It is recommended that you load the TVML file asynchronously and assign it to your player after it has been loaded. After the overlay has been loaded, you can assign it to the player at any time, including during playback.

  • Focusable elements, such as buttons, are not allowed in an overlay.

The divTemplate contains minimal default styling. Ensure that you change the styling for your template to fit your needs. Listing 8-5 shows the code for an overlay template that displays a line of text that is red, 30 pixels high, and centered on the screen.

Listing 8-5OverlayTemplate.xml example
  1. <document>
  2. <head>
  3. <style>
  4. .overlaytext {
  5. color: rgb(255,0,0);
  6. font-size: 30;
  7. text-align: center;
  8. }
  9. </style>
  10. </head>
  11. <divTemplate>
  12. <text class="overlaytext">This is an overlay</text>
  13. </divTemplate>
  14. </document>

To add an overlay to a video, the mediaItems.xml example needs to be modified. Instead of calling the playMedia method directly, a new function, getMedia is called. Listing 8-6 shows the modified mediaItems.xml file.

Listing 8-6MediaItems.xml example (modified)
  1. <document>
  2. <stackTemplate>
  3. <banner>
  4. <title>Available Action Movies</title>
  5. </banner>
  6. <collectionList>
  7. <shelf>
  8. <section>
  9. <lockup onselect="getMedia('path to video', 'video', null)">
  10. <img src="path to image" width="182" height="274"/>
  11. <title>Movie 1</title>
  12. </lockup>
  13. <lockup onselect="getMedia('path to video', 'video', 'path to overlay')">
  14. <img src="path to image" width="182" height="274" />
  15. <title>Movie 2</title>
  16. </lockup>
  17. </section>
  18. </shelf>
  19. </collectionList>
  20. </stackTemplate>
  21. </document>

Listing 8-7 shows a complete TVJS listing that plays video with and without an overlay. The getMedia function takes the URL for the media item, the type of media item, and the URL to the overlay, if it exists. If there is an overlay, that file is loaded and then the media is played. If no overlay is indicated, the media plays immediately.

Listing 8-7Playing video with an overlay example
  1. var baseURL;
  2. function loadingTemplate() {
  3. var template = '<document><loadingTemplate><activityIndicator><text>Loading</text></activityIndicator></loadingTemplate></document>';
  4. var templateParser = new DOMParser();
  5. var parsedTemplate = templateParser.parseFromString(template, "application/xml");
  6. navigationDocument.pushDocument(parsedTemplate);
  7. }
  8. function getDocument(extension) {
  9. var templateXHR = new XMLHttpRequest();
  10. var url = baseURL + extension;
  11. loadingTemplate();
  12. templateXHR.responseType = "document";
  13. templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML);}, false);
  14. templateXHR.open("GET", url, true);
  15. templateXHR.send();
  16. }
  17. function getMedia(extension, mediaType, overlayURL) {
  18. if (overlayURL != null) {
  19. console.log("not null");
  20. var templateXHR = new XMLHttpRequest();
  21. var url = baseURL + overlayURL;
  22. templateXHR.responseType = "document";
  23. templateXHR.addEventListener("load", function() {playMedia(extension, mediaType, templateXHR.responseXML);}, false);
  24. templateXHR.open("GET", url, true);
  25. templateXHR.send();
  26. } else {
  27. console.log("null");
  28. playMedia(extension, mediaType, null);
  29. }
  30. }
  31. function pushPage(document) {
  32. var currentDoc = getActiveDocument();
  33. if (currentDoc.getElementsByTagName("loadingTemplate").item(0) == null) {
  34. console.log("no loading");
  35. navigationDocument.pushDocument(document);
  36. } else {
  37. navigationDocument.replaceDocument(document, currentDoc);
  38. console.log("loading");
  39. }
  40. }
  41. function playMedia(extension, mediaType, overlayDoc) {
  42. var videourl = baseURL + extension;
  43. var singleVideo = new MediaItem(mediaType, videourl);
  44. var videoList = new Playlist();
  45. videoList.push(singleVideo);
  46. var myPlayer = new Player();
  47. myPlayer.playlist = videoList;
  48. myPlayer.overlayDocument = overlayDoc;
  49. myPlayer.play();
  50. }
  51. App.onLaunch = function(options) {
  52. baseURL = options.BASEURL;
  53. var extension = "templates/stackTemplate.xml";
  54. getDocument(extension);
  55. }
  56. App.onExit = function() {
  57. console.log("exited");
  58. }

Figure 8-2 shows an overlay presented on top of a playing video.

Figure 8-2Overlay on a video example output image: ../Art/overlay_2x.png