Chapter 13. Media Player

This section describes the KONtx.mediaplayer interface for TV Apps. Developers creating media apps for a Connected TV device will be able to deliver the best possible media experience for widescreen televisions and support a design that is independent of a particular brand or manufacturer.

In KONtx Framework version 1.3 and above, the KONtx.mediaplayer interface replaces the KONtx.videoplayer interface, which has been deprecated (see the section on Migrating to KONtx.mediaplayer). The KONtx.mediaplayer interface improves the KONtx Framework Media Player API based on lessons learned from a number of Yahoo and third-party implementations of video content apps.

This Media Player API is designed to:

  • Provide the ability to play video when the app is not in focus and/or not in fullscreen mode. The dock can overlay on top of video playback. The sidebar can be visible while the app is playing video content. These features are available when supported by the OEM.
  • Open up the Media Player API to handle alternative forms of content, not just video content. Currently audio and video are supported.
  • Remove requirements on bandwidth detection and content bitrate and make the best assumptions possible based on the data provided.
  • Provide the ability to have late creation of playlist URLs. For content that expires quickly, this allows a TV App developer to delay fetching the content URLs from the backend APIs until the very last moment before playback begins.
  • Provide a singleton interface to the Media Player API.
  • Provide a rich event model to allow a TV App developer to attach hooks throughout the playback life cycle customizing how video is presented to the user.
  • Remove assumptions on data usage and provide as much detail as possible. For example, the KONtx.mediaplayer interface provides the time index value in milliseconds as well as seconds, even though it is only updated once per second.
  • Refine the Media Player API based on the most common use cases. This allows easy implementation of basic functionality while retaining flexibility for advanced customization.
  • Provide accessor methods to access content and player status at any time.
  • Replace the KONtx.videoplayer class. All existing apps that support media playback should migrate to the KONtx.mediaplayer interface.

Media Player Examples

The following sections provided guided examples of how to use the KONtx Media Player API. The following examples are provided:

Basic Example

The first step in this basic example is to initialize the media player. Initialization only needs to happen once, but must be performed before any media playback is started or instantiation of any onscreen controls. Initialization sets up the internal KONtx media player state and binds the handlers to the KONtx Framework low level APIs used to perform video playback.

Next, this example creates an instance of the playlist class. This example uses one of the helper methods to add an entry to the playlist by its URL. Each entry in the playlist is a separate video. If you have multiple streams of the same video with different bitrates, use one of the other examples provided to create your playlist entry.

Following the setup of the playlist, the playlist starts playing. Please note, in this basic example, there are no onscreen controls nor any handlers, so the user interaction is simplified.

Extended Example

This example shows a more complete basic interaction. It adds an onscreen overlay which shows playback buttons and a progress indicator. It also adds a playlist end handler which returns to the previous view. This example has a playlist with two entries, each playlist entry has multiple URLs for the same video with different bitrates. The KONtx media player will choose which bitrate is appropriate given the consumer’s network bandwidth.

For those of you used to the KONtx.videoplayer class, you will notice a couple differences. The first thing is that you no longer have to bind to the transport overlay to the video player. Since the KONtx Media Player API is a singleton, there will always be only just one instance, so it can automatically bind itself. You should also notice that instead of making an abstract data structure there are now typed entities with clear definition. As the KONtx.media.Playlist and KONtx.media.PlaylistEntry classes are normal extendable KONtx classes, you can also extend them for more powerful behavior, as shown in the next example.

Fast Expiring Content Example

This media player example handles content URLs which expire quickly. Usually this is not an issue with playlists of only a single entry, but this can potentially be a problem with multiple entry playlists. The KONtx Media Player API handles expiring content and supports many use cases. This example focuses solely on the custom playlist class and the creation of a playlist.

The example above overrides the streamsReady() function to handle the custom behavior. First it checks if the URLs have been fetched. As soon as you call the provided callback handler, the KONtx media player checks if the streams are ready again. For even more protection, if you know how long your content lasts before expiring you can store the time they were last fetched. If the content is expired, refetch the URLs when the method streamsReady() is called. If you allow looping or give the consumer the ability to repeat this stream, you need to keep track of the expiration of your content URLs.

Be careful to avoid an endless loop. The KONtx Framework will call streamsReady()again after the callback handler is called and keep doing so until streamsReady() returns true or until you stop calling the callback handler. Please also note, the KONtx media player API will silently fail if your code never calls the callback handler. If you get a permanent failure, the suggested approach is to call the callback and not add any content streams. The KONtx media player API will correctly detect that there are no streams available and fire the appropriate error events.

Button Handler Example

By default, the KONtx.control.MediaTransportOverlay shows a play/pause button, a stop button, and a visual indication of the playback progress. By toggling flags in the configuration, you can enable additional buttons for more advanced functionality. The additional buttons that can be enabled are:

  • rewindButton — This button mimics the rewind button on the remote by default. If you override its behavior, you can provide custom handling — for example, increasing the speed increment each time the button is pushed.
  • fastforwardButton — This button mimics the fast forward button on the remote by default. If you override its behavior, you can provide custom handling — for example, increasing the speed increment each time the button is pushed.
  • forwardseekButton — By default, this button does nothing and requires an implementation.
  • backwardseekButton — By default, this button does nothing and requires an implementation.
  • infoButton — By default, this button does nothing and requires an implementation. Typically this is used to show an overlay with meta information for the currently playing entry.
  • resizeButton — By default, this button does nothing and requires an implementation. Typically this is used to toggle the viewport size. To see an example of this being used, see the YouTube app on Samsung 2009 TVs.

To override any button behavior, you subscribe to the overlay’s onTransportButtonPress event. This event is fired with two event.payload properties: button and action. The button property corresponds to a string of the name of the button pressed. The action property indicates the name of the method to be called on KONtx.mediaplayer.control by default if you choose not to call the method event.preventDefault(). The following table shows a mapping between button names, action values, and KONtx media player control methods invoked by default:

event.payload.button

event.payload.action

Default Action Invoked

playpause

play

KONtx.mediaplayer.control.play()

playpause

pause

KONtx.mediaplayer.control.pause()

stop

stop

KONtx.mediaplayer.control.stop()

rewind

rewind

KONtx.mediaplayer.control.rewind()

fastforward

fastforward

KONtx.mediaplayer.control.fastforward()

forwardseek

null

None

backwardseek

null

None

info

null

None

resize

null

None

For the buttons forwardseek, backwardseek, info, and resize, the action property is null. You must provide an event handler with your own implementation as no default action will be taken.

The following example shows the fowardseekButton and provides a handler for it. This example also disables the ability to pause playback via the onscreen control but does not disable pause via the remote control keys:

Playlist Entry Creation Example

The following example shows several ways to add a KONtx.media.PlaylistEntry to a KONtx.media.Playlist:

Dynamic Bookmark Example

The media player interface provides the ability to play video when the app is not in focus and/or not in fullscreen mode. The dock can overlay on top of video playback. The sidebar can be visible while the app is playing video content. These features are available when supported by the OEM.

Pressing the Yahoo TV Key while a streaming video is playing can be configured to bring up the dock over streaming video. Pressing the Yahoo TV Key will close the dock; also pressing the RED key once will close the dock. Pressing the RED key twice will close the dock and close the running app and display fullscreen pass-thru video. See the online developer documentation for Understanding the Fullscreen View for more details on this user interface state.

When the dock is overlaid streaming video, focus is placed on the leftmost bookmark, and the consumer can interact with the dock as usual. To support a visual icon for the currently playing media, a bookmark can be created and pushed onto your app’s bookmark stack. This allows the consumer to return to the fullscreen video by selecting this dynamic bookmark.

This dynamic bookmark’s event handlers should not be created in the fullscreen player view. When focus is on the dock, it is possible for the fullscreen player view to be garbage collected by the Engine. To ensure that the dynamic bookmark’s event handlers are not garbage collected, bind the handlers that define the dynamic bookmark creation and destruction in a script that exists externally from any view. For example, see the MediaPlayerSample app file named event_handlers.js that adds the dynamic bookmark view as follows:

Place the code that subscribes to the onStateChange event in the JavaScript file init.js—for example:

See the JavaScript file now_playing_snippet.js in the MediaPlayerSample app as a template for this dynamic bookmark view.

View Re-entry Example

On OEM platforms that allow dock overlay, special considerations must be made to handle the new app view lifecycle. There are three new interaction cases that need to be considered:

  1. Consumer presses the Yahoo TV Key on the remote control and brings up the dock while playing your content. The user then dismisses the dock via either the RED key or by pressing the Yahoo TV Key again.
  2. Consumer presses the Yahoo TV Key on the remote control and selects your “now playing” bookmark to return to the currently playing video.
  3. Consumer presses the Yahoo TV Key on the remote control and loads up the sidebar of your app again. They then drill down to a specific content item and play it, or they pick the same content they are currently playing.

To handle these cases, you must use code similar to the MediaPlayerSample app code. As you can see in that code (duplicated below), inside the updateView() method there is a call to this._handlePlaylistUpdate() which is a custom method on the view class used to determine if the consumer selected content that is already playing. The first thing you do in that method is to check if any video is already playing. If not, then you know you need to start playing and call the this._startPlaylist() custom view method.

If video is already playing, you need to do checks to cover all use cases above. The first thing you check in this code is to see if you were provided a playlistID in loading the view. In this example, the parameter this.persist.playlistID is set in the MediaPlayer sample app’s sidebar view. Buttons in the sidebar view call KONtx.application.loadView() with the playlistID as a persistent parameter accessible when the next view loads. In your implementation you need to handle setting the playlistID for this case.

If no playlistID exists, then that means you are in interaction case 1 or case 2 above. Since you now know you are already playing the right content, then you simply return immediately as nothing else needs to be done. If you do actually have a playlistID provided, then you check that against the currently playing playlist and see if they match. If they do, again, return immediately. If neither of those matches were met, you then know you have a new playlist to start and you call this.startPlaylist()with the given playlistID.

The following example shows the updateView() method from the MediaPlayer sample app handling re-entry into the fullscreen player view:

Aspect Ratio Example

The default viewport configuration for the media player has the (x,y) position at (0,0) and sets the width and height of the viewport to 1920 x 1080. To use the default viewport configuration for the media player use the following methods:

The default viewport will stretch 4:3 content during playback on some devices. The video playback on the Simulator is not intended to be an indicator of video playback on the Connected TV device. If you want to configure the aspect ratio of video playback for 4:3 content without stretching you can set the viewport properties as follows:

To have video playback within a graphical boundary, for example letterboxing the video, you should create a background image with a transparent area. The graphical plane sits on top of the video plane, so the video will show through the transparent area in your graphical plane’s background image.

Table of Contents