Roku with RAF SDK

This document describes the Roku MediaMelon Player SDK Integration with the Roku media player.

Step 1: Include MediaMelon SmartStreaming SDK

Step 2: Setup a new MediaMelon Task

Step 3: MediaMelon Code Integrate

Step 4: Error Handling

Step 5: Ad Tracking with RAF

Step 6: Variables and Description

Step 1: Include MediaMelon SmartStreaming SDK

To integrate, unzip the MediaMelon Roku library and place the MMSmartStream folder in the components directory.

SDK: MediaMelon Roku IMA SDK

Step 2: Setup a new MediaMelon Task

Create a new XML file MMTask.xml inside your components folder. This is used to link MediaMelon’s brsfiles into your application.

The MMTask.xmlfile should contain the following:

<component name="MMTask" extends="Task">
  <interface>
    <field id="video" type="node" alwaysNotify="true" />
    <field id="config" type="assocarray" alwaysNotify="true" />
    <field id="customConfig" type="assocarray" alwaysNotify="true" />    
    <field id="contentMetadata" type="assocarray" alwaysNotify="true" />
    <field id="customTags" type="assocarray" alwaysNotify="true" />
    <field id="error" type="assocarray" alwaysNotify="true"/>
    <field id="adError" type="assocarray" alwaysNotify="true"/>
    <field id="view" type="String" alwaysNotify="true" />
    <field id="exit" type="Boolean" alwaysNotify="true" />
    <field id="mmAdData" type="assocarray" alwaysNotify="true" />
    <field id="mmAdPlaying" type="Boolean" alwaysNotify="true" />    
    <field id="sdk_version" type="String" alwaysNotify="true" />
    <field id="seekThreshold" type="Integer" alwaysNotify="true"/>
    <field id="codecs" type="assocarray" alwaysNotify="true" />
    <field id="isVideoLive" type="Boolean" alwaysNotify="true" />
  </interface>
  <script type="text/brightscript" uri="pkg:/components/MMSmartStream/MMSmartStreamWrapper.brs" />
  <script type="text/brightscript" uri="pkg:/components/MMSmartStream/MMSmartStreamEngine.brs" />
  <script type="text/brightscript" uri="pkg:/components//MMSmartStream/MMSmartStreamRokuPlugin.brs" />
  <script type="text/brightscript" uri="pkg:/components/MMSmartStream/Utilities.brs" />
</component>

Step 3: MediaMelon Code Integrate

3.1. Add MMTask Child Component:

Add the MediaMelon MMTask as a child component to the main video scene custom-playback-channel-master/components/MainScene.xml

<component name="MainScene" extends="Scene" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
<!-- importing main handler -->
<script type="text/brightscript" uri="pkg:/components/MainScene.brs" />
<children>
    <MMTask id="MM"/>
</children>

3.2. Create MM Task Node:

In the main application, after the video instance has been created, create a MediaMelon Task node, and pass the Video node to it.

CUSTOMER_ID is your MediaMelon assigned Customer ID. If you do not know your Customer ID contact MediaMelon at [email protected].

m.MM = m.top.FindNode("MM")
m.MM.setField("video", m.video)

3.3. Set Configuration Details:

MMConfig = {
  customerID: "CUSTOMER_ID"
  subscriberId: "SUBSCRIBER_ID"
  subscriberType: "SUBSCRIBER_TYPE"
  subscriberTag: "SUBSCRIBER_TAG"
  playerName: "Roku"
  disableManifestFetch: false
  domainName: "DOMAIN_NAME"
  appName: "APP_NAME"
  appSdkVersion: "APP_VERSION"
  viewSessionId: "VIEW_SESSION_ID"
  hashSubscriberId: false 'Important
  enableCustomErrorReporting: true 'Important
}
m.MM.setField("config", MMConfig)
  • disableManifestFetch: If your workflow restricts the manifest to be accessible from both the player and SDK simultaneously, then you can disable manifest fetch. This is an optional step.

  • hashSubscriberId: Set to true to hash the subscriberId and to false to process subscriberId without hashing.

  • enableCustomErrorReporting: If set to true SDK will consider only client-reported errors else if set to false SDK will consider errors from the video node.

3.4. Set Content Metadata:

contentMetadata = {
  "assetName": "ASSET_NAME",
  "assetId": "ASSET_ID",
  "videoId": "VIDEO_ID",
  "genre": "GENRE",
  "drmProtection": "DRM_PROTECTION",
  "episodeNumber": "EPISODE_NUMBER",
  "season": "SEASON",
  "seriesTitle": "SERIES_TITLE",
  "contentType": "CONTENT_TYPE",
}
m.MM.setField("contentMetadata", contentMetadata)

3.5. Set Custom Configuration Details:

customConfig = {
  cdn: "CDN"
  experimentName: "EXPERIMENT_NAME"
  subPropertyId: "SUB_PROPERTY_ID"
  streamFormat: "STREAM_FORMAT"
  mediaType: "MEDIA_TYPE"
  drmProtection: "DRM_PROTECTION"
}
m.MM.setField("customConfig", customConfig)

3.6. Set Codecs:

codecs = {
  video: "VIDEO_CODEC"
  audio: "AUDIO_CODEC"
}
m.MM.setField("codecs", codecs)

3.7. Set Custom Metadata:

customMetadata = {
  "CUSTOM_KEY_1": "VALUE_1",
  "CUSTOM_KEY_2": "VALUE_2"
}
m.MM.setField("customTags", customMetadata)

3.8. Set Seek Threshold:

By default seek threshold is set to 1.25 seconds in the SDK.

m.MM.setField("seekThreshold", 2)

3.9. Set is Video Live:

Set isVideoLive to true for live video stream and to false for VOD stream

m.MM.setField("isVideoLive", true)

3.10. Set View:

It's important to set the view field start for every new view starts and to end when a view ends.

  • Start View:

m.MM.setField("exit", false)
m.MM.setField("view", "start")
  • End View:

m.MM.setField("view", "end")
m.MM.setField("exit", true)

3.11. Run the SDK:

m.MM.control = "RUN"
m.player.setFocus(true)

Step 4: Error Handling

By default, SDK listens to the video node for errors. To report custom errors set enableCustomErrorReporting flag to true in MMConfig and report the errors in the following way;

Upon setting enableCustomErrorReporting flag to true, SDK will stop listening to the video node errors. Only custom errors will be reported.

4.1. Video Error Reporting:

m.MM.error = { 
    errorCode: "ERROR_CODE",
    errorMessage: "ERROR_MESSAGE",
    errorDetails: "ERROR_DETAILS"
}

4.2. Ad Error Reporting:

m.MM.adError = { 
    errorCode: "ERROR_CODE",
    errorMessage: "ERROR_MESSAGE",
    errorDetails: "ERROR_DETAILS"
}

Step 5: Ad Tracking with RAF

    RAF = Roku_Ads()
    RAF.setAdUrl(vastTag)

    logObj = {
        log: function(evtType = invalid as dynamic, ctx = invalid as dynamic)
            'The below function sends the Ad data to MediaMelon SDK for ad tracking
            sendAdDataToMMSDK(ctx)
    }
    logFunc = function(obj = invalid as dynamic, evtType = invalid as dynamic, ctx = invalid as dynamic)
        obj.log(evtType, ctx)
    end function
    RAF.setTrackingCallback(logFunc, logObj)
    
    adPods = RAF.getAds()
function sendAdDataToMMSDK(ctx as object)
    if m.global <> invalid and m.global.MMAnalytics <> invalid
        m.global.MMAnalytics.setField("mmAdData", ctx)
    end if
end function

Set the field named mmAdPlaying to true when an ad break started as shown below:

'preroll ads
if adPods <> invalid and adPods.count() > 0
        video.control = "stop"
        m.top.playingAd = true
        print "Preroll adPods > " adPods
        m.global.MMAnalytics.setField("mmAdPlaying", true) 'This line is part of MM SDK Integration
        keepPlaying = RAF.showAds(adPods, invalid, view)
 end if

'midroll ads
 if adPods <> invalid and adPods.count() > 0
        'ask the video to stop - the rest is handled in the state=stopped event below
        print "Midroll adPods > " adPods
        m.global.MMAnalytics.setField("mmAdPlaying", true) 'This line is part of MM SDK Integration
        video.control = "stop"
 end if

Step 6: Variables and Description

Variable

Description

Optional/Mandatory

PLAYER_NAME

String containing the Player Name.

Mandatory

CUSTOMER_ID

String containing your MediaMelon-assigned Customer ID.

Mandatory

SUBSCRIBER_ID

String containing your Subscriber’s ID.

Mandatory

DOMAIN_NAME

String containing your section of your subscriber or assets.

Mandatory

SUBSCRIBER_TYPE

String containing the Subscriber Type (e.g. “Free”, “Paid”).

Mandatory

SUBSCRIBER_TAG

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

Optional

ASSET_ID

String containing Asset Id.

Mandatory

ASSET_NAME

String containing Asset Name.

Mandatory

VIDEO_ID

String containing your video’s ID.

Mandatory

CONTENT_TYPE

String containing the type of the Content. For example - "Movie", "Special", "Clip", "Scene" or "Episode".

Mandatory

GENRE

String containing the Genre of the content. For example - "Comedy", "Horror".

Mandatory

DRM_PROTECTION

Widevine, Fairplay, Playready, etc. Unknown means content is protected, but the protection type is unknown. For clear contents, do not set this field

Mandatory

EPISODE_NUMBER

String containing sequence number of the Episode.

Mandatory

SEASON

String containing the Season. For example - "Season 1".

Mandatory

SERIES_TITLE

String containing Title of the Series.

Mandatory

VIDEO_TYPE

String containing Video Type. For example - "LIVE", and "VOD".

Optional

PLAYER_BRAND

String containing Player Brand (e.g. “Exo Player”).

Mandatory

PLAYER_MODEL

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

Mandatory

PLAYER_VERSION

String containing Player Version.

Mandatory

CUSTOM_KEY_1

Custom metadata key can be added here if required.

Optional

VALUE_1

Custom metadata value can be added here if required.

Optional

BASE_PLAYER_NAME

String containing base player name

Optional

BASE_PLAYER_VERSION

String containing base player version

Optional

EXPERIMENT_NAME

You can use this field to categorise views into different experiments, allowing you to filter by this dimension later.

Optional

SUB_PROPERTY_ID

A sub-property is an optional feature that allows you to organize data within a property. For instance, a video platform could use sub-properties to group data by customer, or a media company might use them to differentiate between its various websites.

Optional

VIEW_SESSION_ID

An ID that can be used to link the view with upstream platform services, such as CDN or origin logs, for correlation purposes.

Optional

hashSubscriberId

To hash the subscriber ID set this boolean variable to true, else set it to false.

Optional

player

Player Object.

Mandatory

streamURL

Current playing content stream URL.

Mandatory

isVideoLive

Set this boolean variable to true if the content is Live else set it to false for VOD content.

Optional

Last updated

Was this helpful?