ExoPlayer 2.18.5/2.19.1 (Media3) With Nowtilus SSAI

Contains details of how to integrate the Nowtilus Android SSAI SDK with ExoPlayer 2.18.5 and 2.19.1

STEP 1 :

Prerequisites

STEP 2: Add the .jar file as a dependency in the Exoplayer build.gradle file.

api files ('smartstreaming-release.aar')

STEP 3: Add the below lines to the Exoplayer Application level class and PlayerActivity.java.

import com.mediamelon.smartstreaming.MMQBRMode;
import com.mediamelon.smartstreaming.MMSmartStreaming;
import com.mediamelon.smartstreaming.MMSmartStreamingExo2;
import com.mediamelon.smartstreaming.MMSmartStreamingInitializationStatus;
import com.mediamelon.smartstreaming.MMSmartStreamingObserver;
import com.mediamelon.qubit.PropertyReader;

STEP 4 :Register Mediamelon SDK using your assigned customerID.

Add the below lines in the onCreate method of Application level

set the hashSubscriberId variable for in registerMMSmarttreaming() API subscriberId hashing, set to true for hashing else false. (optional).


 MMSmartStreamingExo2.enableLogTrace(true); //set to "false" before releasing player to production
 if (MMSmartStreamingExo2.getRegistrationStatus() == false){
  //Check if it is the first time Registration process is done
   // Please make the registration API call based on the version of the SDK you are using.
   MMSmartStreamingExo2.registerMMSmartStreaming("$PLAYERNAME", "$CustomerID", "$SUBSCRIBERID", "$DOMAINNAME", "$SUBSCRIBERTYPE", "$SUBSCRIBERTAG","$doHash");
   MMSmartStreamingExo2.reportPlayerInfo("$PlayerBrand", "$PlayerModel", "$PlayerVersion");
   MMSmartStreamingExo2.getInstance().setContext(getApplicationContext()); //Please make sure to provide the application's context here, and not the activity's context
   MMSmartStreamingExo2.setDeviceInfo($DEVICE_MARKETING_NAME);
   MMSmartStreamingExo2.getInstance().reportAppInfo($APP_NAME,$APP_VERSION);
   MMSmartStreamingExo2.getInstance().reportVideoQuality($VIDEO_QUALITY);
 }
  
Variable
Description

$PLAYERNAME

Player Name as in ExoPlayer, KalturaPlayer etc.

$CUSTOMERID

String containing your MediaMelon-assigned Customer ID.

$SUBSCRIBERID

String containing your subscriber’s ID. If you do not use subscriber IDs, leave it as it is.

$DOMAINNAME

String containing your section of your subscriber or assets. (Optional)

$SUBSCRIBERTYPE

String containing the subscriber type (e.g. “Free”, “Paid”). If you do not use subscriber types, leave it as it is.

$SUBSCRIBERTAG

String containing an additional subscriber-specific information. This is sent in clear (not hashed) to SmartSight and it is advised to not send sensitive information in this field.

$ASSETID

String containing Asset Id.

$ASSETNAME

String containing Asset Name.

$VIDEOID

String containing your video’s ID. If you do not use videos IDs, leave it as it is.

$PLAYER_BRAND

String containing the player brand (e.g. “Exo”).

$PLAYER_MODEL

For example - This could be a variant of player. Say name of third party player used by organisation. Or any human readable name of the player

$PLAYER_VERSION

String containing the player version.

STEP 5: Create the Content Metadata object inside the initializePlayer() method of PlayerActivity.java .

String assetId  = "assetID"; //enter you assetId here
String assetName = "assetNAME"; // enter your assetname here 
String videoId = "videoID"; // enter your videoId here 
ContentMetadata cm  = new ContentMetadata();
String episodeNumber = "EpisodeNumber";
String season = "Season";
String genre = "Genre";
String drmProtection = "drmProtection";
String contentType = "contentType";
String title = "Title";
cm.videoId=videoId;
cm.seriesTitle=title;
cm.season=season;
cm.genre=genre;
cm.episodeNumber=episodeNumber;
cm.drmProtection=drmProtection;
cm.contentType=contentType;
cm.assetName=assetName;
cm.assetId=assetId;
JSONObject contentMetadata = cm.getJSONObject();

STEP 6: Get the mediaURL and vastURL from the Nowtilus SSAI stream url.

NOTE - The player needs to be given the extracted mediaURL as the playback URL.

String streamURL = "NOWTILUS SSAI URL";
/*
The streamURL gives the mediaURL and VastURL as a response as shown below ,extract the mediaURL and vastURL from the response
*/
{"mediaURL":"https://ssaipre.serverside.ai/hls/f18e5f62-230a-4cad-baf7-3d0e6d429aa7/master.m3u8?sid=75291960-6256-11ec-823d-5bdd72099bb9&api-key=31c8e40a-ee55-4a49-8af2-c76375b22b6e","vastURL":"https://ssaipre.serverside.ai/hls/f18e5f62-230a-4cad-baf7-3d0e6d429aa7/75291960-6256-11ec-823d-5bdd72099bb9/vast.xml"}

STEP 7: Add the below lines to the initializePlayer() method. Add the lines after the player is initialized and not null.

NOTE - boolean enablePollingforSSAI variable indicates whether the Mediamelon SDK needs to poll for the VAST URL or not. Please set it to true if you want to opt for polling else set it to false.

boolean clientSideTracking variable indicates, whether Mediamelon SDK needs to fire tracking urls.

boolean isLive variable in setupNowtilusAdManager() indicates, whether it is a Live stream or VOD stream.

private void initializePlayer() {
...
...
...
...
MMSmartStreamingExo2.getInstance().initializeSession(player, MMQBRMode.QBRModeDisabled, "Extracted MediaURL from Nowtilus SSAI streamURL", null, assetId, assetName, videoId,null,contentMetadata,isLive);
MMSmartStreamingExo2.getInstance().reportUserInitiatedPlayback();
MMSmartStreamingExo2.getInstance().vastURLfromApplication ="extracted vastURL from the NOwtilus SSAI URL";
boolean enablePollingforSSAI = false; // set to true if you want to poll for vast
//calling Nowtilus Ad Manager 
MMSmartStreamingExo2.getInstance().setupNowtilusAdManager("Extracted MediaURL from Nowtilus SSAI streamURL","Extracted vastURL from the NOwtilus SSAI URL",isLive,enablePollingforSSAI,vodResponseData,clientSideTracking);

isLive variable in initializeSession call indicates whether it is Live stream or not.(optional)

STEP 8: Add Macro Parameters API

getMacros() API returns the JSONObject which contains all Macros that needs to be substituted in Tracking Urls. You can add any new Macros to added in getMacros() API

JSONObject getMacros() {
  JSONObject jsonObject = new JSONObject();
  try {
    jsonObject.put("key","value");
    jsonObject.put("key","value");
    jsonObject.put("key","value");
    
    JSONObject obj = new JSONObject();
    obj.put("key","value");
    
    jsonObject.put("obj",obj);
    
      } catch (JSONException e) {

  }
  return jsonObject;
}

STEP 9: Subscribe to AD EVENTS and Pass the Macros to SSAI.

Passing Macros to SSAI with the help of setMacroSubstitution() API. getMacros() API will return the Macros in JSON format.

MMSmartStreamingNowtilusSSAIPlugin mmSmartStreamingNowtilusSSAIPlugin = MMSmartStreamingExo2.getInstance().getSSAIAdManager();

//passing Macros to SSAI using setMacroSubstitution
  mmSmartStreamingNowtilusSSAIPlugin.setMacroSubstitution(getMacros())

//Subscribing to AD Events
MMSSAIEventsListeners mmssaiEventsListeners = new MMSSAIEventsListeners() {
  @Override
  public void onAdImpression(mmAd ssaiAdInfo) {
  }

  @Override
  public void onAdComplete(mmAd ssaiAdInfo) {
  }
  @Override
  public void onCueTimelineEnter(mmAd ssaiAdInfo) { 
  }

  @Override
  public void onCueTimelineExit(mmAd ssaiAdInfo) {  
  }

  @Override
  public void onCueTimelineAdded(mmAdTimelineInfo timelineInfo) {  
  }
};
mmSmartStreamingNowtilusSSAIPlugin.addListener(mmssaiEventsListeners);

List of AD EVENTS

onAdImpression
onAdStarted
onAdFirstQuartile
onAdMidpoint
onAdThirdQuartile
onAdProgress
onAdComplete
onCueTimelineAdded 
onCueTimelineEnter
onCueTimelineExit
Event Callback
Description

onAdImpression

Fired when an Ad Impression occurs

onAdStarted

Fired when Ad starts playing

onAdFirstQuartile

Fired when Ad playback reaches the First Quartile point

onAdMidpoint

Fired when Ad playback reaches the Midpoint

onAdThirdQuartile

Fired when Ad playback reaches the Third Quartile point

onAdProgress

Fired every second during Ad Playback, used to track Ad Playback progress

onAdComplete

Fired when Ad Playback completes

onCueTimelineAdded

Fired when an Ad break information gets added

onCueTimelineEnter

Fired when an Ad break ( which can contain multiple Ads) starts

onCueTimeLineExit

Fired when an Ad break ( which can contain multiple Ads) ends

STEP 10: Add the below lines to the releasePlayer() method.

 protected void releasePlayer() {
    if (player != null) {
      MMSmartStreamingExo2.getInstance().reportPlayerState(false, Player.STATE_ENDED); 
    }
  }

You can use the below commands from inside any of the AD Events(listed above) that you subscribe to.

  1. ssaiAdInfo.getTotalAds()- returns a int which signifies the number of Ads in the current Ad break.

  2. ssaiAdInfo.getClickTrackingURLs()-returns the click tracking URLs as a List<String>.

  3. ssaiAdInfo.getClickThroughURLs() -returns the clickthrough URLs as a List<String>.

  4. ssaiAdInfo.getAdSkipOffset()- returns the AD offset in seconds.

  5. ssaiAdInfo.getCompleteTrackers() - returns the AD Complete Tracking URLs as a List<String>.

  6. ssaiAdInfo.getMidpointTrackers() - returns the AD Midpoint Tracking URLs as a List<String>.

  7. ssaiAdInfo.getThirdQuartileTrackers() - returns the AD ThirdQuartile Tracking URLs as a List<String>.

  8. ssaiAdInfo.getFirstQuartileTrackers() - returns the AD FirstQuartile Tracking URLs as a List<String>.

  9. ssaiAdInfo.getImpressionTrackers() - returns the AD Impression URLs as a List<String>.

  10. ssaiAdInfo.getAdIndex() - returns the index of the current AD in the AD break.

  11. To fire the clickTracking url, need to make the API call from sample application as below

mmSmartStreamingNowtilusSSAIPlugin.fireTrackingUrl("$<String>EventName","$List<String>clickUrls")

// pass Event name as ClickTracking in 1st parameter
//pass clickUrls, the we get from ssaiAdInfo.getClickTrackingURLs()

Sample Application

The Sample Application for Exoplayer with Nowtilus SSAI can be donwloaded from

https://mediamelon-builds.s3.amazonaws.com/MM-RELEASE-BUILDS/SDK_RELEASES/Android/2023-12-13/exo-2.18.5/demos.zip

Complete Integration

Inside onCreate method


 MMSmartStreamingExo2.enableLogTrace(true); //set to "false" before releasing player to production
 if (MMSmartStreamingExo2.getRegistrationStatus() == false){
  //Check if it is the first time Registration process is done
   // Please make the registration API call based on the version of the SDK you are using.
   MMSmartStreamingExo2.registerMMSmartStreaming("$PLAYERNAME", "$CustomerID", "$SUBSCRIBERID", "$DOMAINNAME", "$SUBSCRIBERTYPE", "$SUBSCRIBERTAG","$doHash");
   MMSmartStreamingExo2.reportPlayerInfo("$PlayerBrand", "$PlayerModel", "$PlayerVersion");
   MMSmartStreamingExo2.getInstance().setContext(getApplicationContext()); //Please make sure to provide the application's context here, and not the activity's context
   MMSmartStreamingExo2.setDeviceInfo($DEVICE_MARKETING_NAME);
   MMSmartStreamingExo2.getInstance().reportAppInfo($APP_NAME,$APP_VERSION);
   MMSmartStreamingExo2.getInstance().reportVideoQuality($VIDEO_QUALITY);
 }
  

Inside the initializePlayer() method

String assetId  = "assetID"; //enter you assetId here 
String assetName = "assetNAME"; // enter your assetname here
String videoId = "videoID"; // enter your videoId here 
ContentMetadata cm  = new ContentMetadata();
String episodeNumber = "EpisodeNumber";
String season = "Season";
String genre = "Genre";
String drmProtection = "drmProtection";
String contentType = "contentType";
String title = "Title";
cm.videoId=videoId;
cm.seriesTitle=title;
cm.season=season;
cm.genre=genre;
cm.episodeNumber=episodeNumber;
cm.drmProtection=drmProtection;
cm.contentType=contentType;
cm.assetName=assetName;
cm.assetId=assetId;
JSONObject contentMetadata = cm.getJSONObject();

MMSmartStreamingExo2.getInstance().initializeSession(player, MMQBRMode.QBRModeDisabled, "Extracted MediaURL from Nowtilus SSAI streamURL", null, assetId, assetName, videoId,null,contentMetadata,isLive);
MMSmartStreamingExo2.getInstance().reportUserInitiatedPlayback();
MMSmartStreamingExo2.getInstance().vastURLfromApplication ="extracted vastURL from the NOwtilus SSAI URL";
boolean enablePollingforSSAI = false; // set to true if you want to poll for vast
MMSmartStreamingExo2.getInstance().setupNowtilusAdManager("Extracted MediaURL from Nowtilus SSAI streamURL","Extracted vastURL from the NOwtilus SSAI URL",isLive,enablePollingforSSAI,vodResponseData,clientSideTracking);

//get the SSAI Admanager and subscribe to events
MMSmartStreamingNowtilusSSAIPlugin mmSmartStreamingNowtilusSSAIPlugin = MMSmartStreamingExo2.getInstance().getSSAIAdManager();

mmSmartStreamingNowtilusSSAIPlugin.setMacroSubstitution(getMacros())

MMSSAIEventsListeners mmssaiEventsListeners = new MMSSAIEventsListeners() {
  @Override
  public void onAdImpression(mmAd ssaiAdInfo) {
  }

  @Override
  public void onAdComplete(mmAd ssaiAdInfo) {
  }
  @Override
  public void onCueTimelineEnter(mmAd ssaiAdInfo) { 
  }

  @Override
  public void onCueTimelineExit(mmAd ssaiAdInfo) {  
  }

  @Override
  public void onCueTimelineAdded(mmAdTimelineInfo timelineInfo) {  
  }
};
mmSmartStreamingNowtilusSSAIPlugin.addListener(mmssaiEventsListeners);

Inside the releasePlayer() method

 protected void releasePlayer() {
    if (player != null) {
      MMSmartStreamingExo2.getInstance().reportPlayerState(false, Player.STATE_ENDED); 
    }
  }

Last updated