Skip to main content
Skip table of contents

Harmonic WebVTT thumbnails example code

To test this feature and view the example code, please see the Android SDK 5 Example Code Quick Start guide.

Importing classes

The application needs to import the classes.

JAVA
import nagra.otv.sdk.harmonicthumbnails.OTVHarmonicThumbnailController;
import nagra.otv.sdk.harmonicthumbnails.OTVHarmonicThumbnailView;
import nagra.otv.sdk.harmonicthumbnails.HarmonicThumbnail;
import nagra.otv.sdk.harmonicthumbnails.OTVHarmonicThumbnailListener;

Preparing the listener

The operation is instigated by creating an OTVVideoView instance and an OTVHarmonicThumbnailController instance with an OTVHarmonicThumbnailListener implementation. The controller is started by passing the thumbnail URI after setting the video path URI to the OTVVideoView. The listener interface listens to the signals triggered when thumbnails are requested and processed, and a prepared callback in the listener provides an OTVHarmonicThumbnailView instance that is attached to the OTVVideoView to display the thumbnails.

Upon starting, the controller instantiates the OTVHarmonicThumbnailView and the HarmonicThumbnailParser. The parser receives the thumbnail URI from the controller and starts parsing the thumbnail WebVTT. On success, the parser returns an HarmonicThumbnailPlaylist that provides an updated thumbnails list to the controller which triggers the listener callback thumbnailUpdate. The OTVHarmonicThumbnailView then downloads the image data for the requested position, decoding and displaying them in an imageView.

Click here to see the example code.
JAVA
public class AppThumbnailListener implements OTVHarmonicThumbnailListener {
    private final static String TAG = "AppThumbnailListener";
    private OTVVideoView mPlayerView;
    private ThumbnailMediaController mMediaController;
    private OTVHarmonicThumbnailView mCurrentView;

    public AppThumbnailListener(OTVVideoView view, ThumbnailMediaController mediaController) {
        this.mPlayerView = view;
        this.mMediaController = mediaController;
    }
    @Override
    public void noThumbnails() {
        // Couldn't find thumbnails for the given stream
        Log.d(TAG, "Selected stream has no thumbnails in the manifest");
    }

    @Override
    public void preparing() {
        // Got a DASH manifest with thumbnails. Preparing thumbnails
        Log.d(TAG, "Found thumbnails in this stream. Please wait until they are available");
    }

    @Override
    public void prepared(OTVHarmonicThumbnailView xView) {
        if(mCurrentView != null)
            return;
        mMediaController.setThumbnailView(xView);
        mCurrentView = xView;
        new Handler(Looper.getMainLooper()).post(() -> mPlayerView.addView(xView));
    }

    @Override
    public void error(int reason) {
        // Failed to fetch thumbnails for some reason
        Log.w(TAG, "Error preparing thumbnails. Reason - " );
    }

    @Override
    public void thumbnailUpdate(List<HarmonicThumbnail> list){
        Log.d(TAG, "Update harmonic thumbnail");
        mCurrentView.update(list);
    }
}

Preparation time (the time it takes from the start of playback until thumbnails are available for preview) depends on the number of thumbnails and their size (bandwidth). This could take a fraction of a second for short content with few thumbnails to several seconds for long-duration content with a high density of thumbnails. The OTVHarmonicThumbnailView instance provided in the prepared() callback is used to display all thumbnails. The application updates the view with the correct image by specifying the desired time and the SDK matches the position (in milliseconds) with the correct thumbnail image.

The application needs to attach the OTVHarmonicThumbnailListener to the player view and set the OTVHarmonicThumbnailListener instance to the OTVHarmonicThumbnailController in the onCreate() before setting the video path.

Click here to see the example code.
JAVA
private OTVVideoView mOTVVideoView;
private OTVHarmonicThumbnailController mHarmonicController;
private AppThumbnailListener mThumbnailEventListener;

 @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // The OTVSDK.load() method must be called before SDK can be used
    // You may wish to do this in an application class
    OTVSDK.load(this);
    ....
    ....
    mThumbnailEventListener = new AppThumbnailListener(mOTVVideoView, mMediaController);
    mHarmonicController  = new OTVHarmonicThumbnailController(this);
    mHarmonicController.setThumbnailListener(mThumbnailEventListener);
    
    mOTVVideoView.setOnPreparedListener((MediaPlayer mp) -> {
      // Only once we get this event, the media controller would have access to properties such
      // as duration or position
      mMediaController.startMediaController();
      // Start playback
      mOTVVideoView.start();
    });

    mFrame.addView(mOTVVideoView);

  }

Seek methods

The example code implements a simple seek bar in a ThumbnailMediaController class which demonstrates the usage of the thumbnail view provided in the prepared() callback.

Click here to see the example code.
JAVA
if (durationMs > 0) {
// for vod playback
   updateThumbPos(bar, progress);
   if (mThumbnailPreview != null) {
      mThumbnailPreview.seekTimewithPosition(progress);
   }
}
else {
//    for live playback thumbnail
   long[] seekableRange = mPlayerView.getSeekableRangeInfo();
   if(seekableRange != null) {
      long endRange = seekableRange[1];
      long timeNow = System.currentTimeMillis();
      if (mThumbnailPreview != null && endRange > 0) {
        long availableSeekRange = getAvailableSeekableRange();
        if (availableSeekRange > 0) {
          long positionOffset = (availableSeekRange-progress);
          updateThumbPos(bar, progress);
          mThumbnailPreview.seekTimewithEpoch(timeNow - positionOffset);
        }
      }
  }
}

Starting the Harmonic thumbnail controller

After starting the player view and setting the video path, the application must start the OTVHarmonicThumbnailController by passing the parameter <thumbnailURL>. The thumbnailURL is a JSON file explicitly generated and hosted on the Harmonics CDN for every videoURL that contains the harmonics thumbnails metadata in vtt format corresponding to the particular videoURL.

JAVA
mOTVVideoView.setVideoPath(videoURL);
mHarmonicController.start(thumbnailURL);

Stopping the Harmonic thumbnail controller

When playback is stopped, the application has to stop the OTVHarmonicThumbnailController.

JAVA
if(mOTVVideoView.isPlaying()) {
  mHarmonicController.stop();
  mOTVVideoView.stopPlayback();
}

Thumbnail bandwidth

Bandwidth management is not currently implemented for Harmonic thumbnails. Thumbnail preparation time and memory requirements increase with the bandwidth. As an entire set of thumbnails (List<OTVThumbnail> thumbnails) is stored in the device’s memory during playback, selecting a set of high bandwidth thumbnails, especially with long-content VOD, can use up much of the application’s usable memory. If available memory is exhausted, the SDK will send an Out of memory error to the thumbnail listener and discard the entire set of thumbnails.  For Live playback, the thumbnails are not appended to List<OTVThumbnail> thumbnails.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.