Roku with IMA SDK

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

Step 1: Include MediaMelon SmartStreaming SDK

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

Step 2: Setup a new MediaMelon Task

Create a new XML file MMTask.xmlinside 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="customTags" type="assocarray" alwaysNotify="true"/>
    <field id="contentMetadata" type="assocarray" alwaysNotify="true"/>
    <field id="error" type="assocarray" alwaysNotify="true"/>
    <field id="view" type="String" alwaysNotify="true"/>
    <field id="exit" type="Boolean" alwaysNotify="true"/>
    <field id="imaads" type="assocarray" alwaysNotify="true"/>
    <field id="isAdImpressionSent" type="Boolean" alwaysNotify="true"/>
    <field id="sdk_version" type="String" 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: Integrate MediaMelon Code to Main Application

3.1: Add 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: 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 support@mediamelon.com

'Mandatory fields are customerID and subscriberId.'
MMConfig = {
  customerID : "CUSTOMER_ID"
  subscriberId : "SUBSCRIBER_ID"
  subscriberType: "SUBSCRIBER_TYPE"
  subscriberTag: "SUBSCRIBER_TAG"
  playerName: "PLAYER_NAME"
  disableManifestFetch: false
  domainName: "DOMAIN_NAME"
  appName: "APP_NAME"
  appSdkVersion: "APP_VERSION"
}

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

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

customMetadata = {
    "key1": "VALUE_STRING1",
    "key2": "VALUE_STRING2",
    "key3": "VALUE_STRING3"
}
m.MM.setField("customTags", customMetadata)

m.MM.control = "RUN"
m.player.setFocus(true)
m.player.observeField("state", "videoStateChange")

There is an upper limit of 3 custom tags that can be sent to SmartSight. If you need to send more tags, please contact your MediaMelon sales representative.

If your workflow restricts the manifest to be accessible from both player and SDK simultaneously, then, you can disable manifest fetch. This is a optional step.

3.3: For Live streams contentNode.live has to be set to true

contentNode.live = true

Step 4: Error handling

In most cases the Error handling in Roku applications is done by an Error Handler at the application level. For passing on the errors to the Media Melon SDK the following code snippet needs to be added to the error handling function.

'Send the error message to the MM SDK
m.MM.error = { errorMsg : m.video.errorMsg }

Google IMA Ads Integration

This guide demonstrates how to integrate the Mediamelon Roku SDK into a sample video player app with Google Ima Ads, downloaded the basic example from GitHub.

There are three APIs that are exported from MediaMelon Roku IMA Ads Plugin from MMImaAdsPlugin.brs

  • Notify AdBreakStart

  • Notify AdBreakEnded

  • Add MediaMelon Callbacks

1. Include MMImaAdsPlugin.brs IMA plugin file into SDK.xml as shown below

<?xml version = "1.0" encoding = "utf-8" ?>

<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
  ' Your code goes here.
]]>
</script>
' MediaMelon IMA AdPlugin'
<script type = "text/brightscript" uri="pkg:/Components/MMSmartStream/MMImaAdsPlugin.brs"/>
</component>

2. Create an IMA stream player

This implements three callback methods: loadUrl, adBreakStarted, and adBreakEnded.Call MediaMelon APIs to notify adBreakStarted and adBreakEnded as shown below

...
sub setupVideoPlayer()
  sdk = m.sdk
  m.player = sdk.createPlayer()
  m.player.top = m.top
  m.player.loadUrl = Function(urlData)
    m.top.video.enableTrickPlay = false
    m.top.urlData = urlData
  End Function
  m.player.adBreakStarted = Function(adBreakInfo as Object)
    print "---- Ad Break Started ---- "
    m.top.adPlaying = True
    m.top.video.enableTrickPlay = false
    mmAdBreakStarted(adBreakInfo)     ' MediaMelon API to notify AdBreakStart'
  End Function
  m.player.adBreakEnded = Function(adBreakInfo as Object)
    print "---- Ad Break Ended ---- "
    m.top.adPlaying = False
    m.top.video.enableTrickPlay = true
    mmAdBreakEnded(adBreakInfo)       ' MediaMelon API to notify AdBreakEnd'
  End Function
End Sub

3. Add event listeners and start the stream

After requesting your stream, add event listeners to track ad progress from MediaMelon SDK by calling an APIaddMediaMelonAdCallbacks

Sub loadStream()
  sdk = m.sdk
  sdk.initSdk()
  setupVideoPlayer()
  request = sdk.CreateStreamRequest()
  if m.top.streamData.type = "live"
    request.assetKey = m.top.streamData.assetKey
  else
    request.contentSourceId = m.top.streamData.contentSourceId
    request.videoId = m.top.streamData.videoId
  end if
  request.apiKey = m.top.streamData.apiKey
  request.player = m.player

  requestResult = sdk.requestStream(request)
  If requestResult <> Invalid
    print "Error requesting stream ";requestResult
  Else
    m.streamManager = Invalid
    While m.streamManager = Invalid
      sleep(50)
      m.streamManager = sdk.getStreamManager()
    End While
    If m.streamManager = Invalid or m.streamManager["type"] <> Invalid or m.streamManager["type"] = "error"
      errors = CreateObject("roArray", 1, True)
      print "error ";m.streamManager["info"]
      errors.push(m.streamManager["info"])
      m.top.errors = errors
    Else
      m.top.streamManagerReady = True
      addCallbacks()
      addMediaMelonAdCallbacks(m.sdk, m.streamManager) ' MediaMelon Callback register'
      m.streamManager.start()
    End If
  End If
End Sub

Last updated