# MediaMelon Roku SDK Integration Document

**Step 1:** [Include MediaMelon SmartStreaming SDK](#step-1-include-mediamelon-smartstreaming-sdk)

**Step 2:** [Set up a new MediaMelon Task](#step-2-setup-new-mediamelon-task)

**Step 3:** [MediaMelon Code Integration](#step-3-integrate-mediamelon-code-to-main-application)

**Step 4:** [Request Information](#step-4-request-information)

**Step 5:** [Error Handling](#step-5-error-handling)

**Step 6:** [Custom Events](#step-6-custom-events)

[Release Notes](#release-notes)

### Step 1: Include MediaMelon SmartStreaming SDK <a href="#step-1-include-mediamelon-smartstreaming-sdk" id="step-1-include-mediamelon-smartstreaming-sdk"></a>

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

SDK: [MediaMelon Roku SDK](https://sdks.mediamelon.com/roku/qoe/2.10.0/MMSmartStream.zip)

### Step 2: Set up a new MediaMelon Task <a href="#step-2-setup-new-mediamelon-task" id="step-2-setup-new-mediamelon-task"></a>

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

The `MMTask.xml`file should contain the following:

```xml
<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="mmRafEvent" type="assocarray" 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" />
    <field id="requestInfo" type="assocarray" alwaysNotify="true" />
    <field id="customEvent" type="assocarray" 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 Integration <a href="#step-3-integrate-mediamelon-code-to-main-application" id="step-3-integrate-mediamelon-code-to-main-application"></a>

#### 3.1. 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.

{% hint style="info" %}
`CUSTOMER_ID` is your MediaMelon assigned Customer ID. If you do not know your Customer ID, contact MediaMelon at <customer-support@mediamelon.com>.
{% endhint %}

```raku
m.MM = createObject("roSGNode", "MMTask")
m.MM.setField("video", m.video)
```

#### 3.2. Set Configuration Details:

```raku
MMConfig = {
  customerID: "CUSTOMER_ID"
  subscriberId: "SUBSCRIBER_ID"
  subscriberType: "SUBSCRIBER_TYPE"
  subscriberTag: "SUBSCRIBER_TAG"
  playerName: "PLAYER_NAME"
  playerId: "PLAYER_ID"
  playerVersion: "PLAYER_VERSION"
  basePlayerName: "BASE_PLAYER_NAME"
  basePlayerVersion: "BASE_PLAYER_VERSION"
  disableManifestFetch: true
  domainName: "DOMAIN_NAME"
  appName: "APP_NAME"
  appSdkVersion: "APP_VERSION"
  viewSessionId: "VIEW_SESSION_ID"
  appSessionId: "APP_SESSION_ID"
  hashSubscriberId: false 'Important
  enableCustomErrorReporting: true 'Important
}
m.MM.setField("config", MMConfig)
```

{% hint style="info" %}

* `disableManifestFetch`: If your workflow restricts the manifest to be accessible from both the player and SDK simultaneously, you can disable manifest fetch. This is an optional step.
* `hashSubscriberId`: Set `true` to hash the subscriberId and to `false` to process the 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. ([Refer Here](#step-4-error-handling))
  {% endhint %}

#### 3.3. Set Content Metadata:

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

#### 3.4. Set Custom Configuration Details:

```raku
customConfig = {
  cdn: "CDN"
  experimentName: "EXPERIMENT_NAME"
  subPropertyId: "SUB_PROPERTY_ID"
  streamFormat: "STREAM_FORMAT"
  mediaType: "MEDIA_TYPE"
  drmProtection: "DRM_PROTECTION"
  drmLevel: "DRM_LEVEL"
  preload: <boolean>
  encodingService: "ENCODING_SERVICE"
}
m.MM.setField("customConfig", customConfig)
```

#### 3.5. Set Codecs:

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

#### 3.6. Set Custom Metadata:

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

{% hint style="info" %}
For Custom Metadata, first, provide the mapping in the [SmartSight](https://smartsight3.mediamelon.com/settings) dashboard under the settings section, and send the values to the SDK accordingly.
{% endhint %}

#### 3.7. Set Seek Threshold:

By default seek threshold is set to `1.25 seconds` in the SDK.&#x20;

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

#### 3.8. Set is Video Live:

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

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

#### 3.9. Set View:

{% hint style="info" %}
It's important to set the view field  `start` for every new view start, and to `end` when the view ends.
{% endhint %}

* **Start View:**

```raku
m.MM.setField("exit", false)
m.MM.setField("view", "start")
```

* **End View:**

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

#### 3.10. Run the SDK:

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

### Step 4: Request Information

Report `failed` or `cancelled` requests for the following request types:

* PIR
* MANIFEST
* AUDIO\_CHUNK
* VIDEO\_CHUNK
* DRM
* SUBTITLE

```raku
requestInfo = { 
    requestStatus: <request_status>,    'string (This should be "failed" or "cancelled")
    requestType: <request_type>,        'string (This can be pir, manifest, audio_chunk, video_chunk, drm, subtitle)
    id: "ID",
    error: "ERROR",
    text: "TEXT",
    hostname: "HOSTNAME",
    url: "URL"
}

m.MM.setField("requestInfo", requestInfo)
```

### Step 5: Error Handling

By default, the 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;

{% hint style="info" %}
Upon setting `enableCustomErrorReporting` flag to true, SDK will stop listening to the video node errors. Only custom errors will be reported.
{% endhint %}

#### 5.1. Video Error Reporting:

```raku
m.MM.error = { 
    errorCode: "ERROR_CODE",
    errorMessage: "ERROR_MESSAGE",
    errorDetails: "ERROR_DETAILS",
    errorSeverity: <error_severity>   'string (This should be "warning" or "fatal")
}
```

{% hint style="info" %}
`error_severity`: Set this to `"warning"` for warnings and set to `"fatal"` for fatal errors.
{% endhint %}

#### 5.2. Ad Error Reporting:

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

#### Step 6: Custom Events:

The Custom Events API can be used to report events that are not covered by the default MediaMelon-supported events. Custom events must be reported within the SDK activity lifecycle. Events reported before SDK initialization or after session end will be ignored. Please refer to the guidelines and constraints below.

```raku
m.MM.customEvent = {
    eventName: "EVENT_NAME",
    eventValue: "EVENT_VALUE"
}
```

{% hint style="info" %}
**Guidelines & Constraints**

* **Event Name**
  * Maximum length: 35 characters
  * Allowed characters: Alphanumeric and underscore (\_) only
  * Special characters are not supported
  * Recommended format: UPPERCASE with underscores (e.g., DRM\_CHANGE)
* **Event Limits**
  * A maximum of 35 custom events per session is allowed.

Custom events that violate these constraints (invalid event name or exceeding the per-session limit) will be dropped. Event values exceeding 1000 characters will be truncated to 1000 characters.
{% endhint %}

#### Release Notes

<details>

<summary>Current Release</summary>

#### v2.10.0[^1]  <sup><sub>**`May 06, 2026`**<sub></sup>

* Added new metadata fields `player ID` and `DRM Level`.
* Fixed play duration offset calculation issue.

</details>

***

<details>

<summary>Previous Releases</summary>

#### v2.9.0[^1]  <sup><sub>**`Mar 30, 2026`**<sub></sup>

* Added support for reporting a new field encoding service via `customConfig`.
* Introduced custom event reporting through `customEvent` interface.
* Added FPS reporting in the Rendition event.
* Fixed the `NA` Asset Name issue.

#### v2.8.0[^1]  <sup><sub>**`Feb 06, 2026`**<sub></sup>

* Added `CDN_CHANGE` event functionality.
* Added Seek Duration calculation internally.
* Added Audio and Video Codecs in Rendition Event.

#### v2.7.2[^1]  <sup><sub>**`Jan 23, 2026`**<sub></sup>

* Cleaned up the content change handler

#### v2.7.1[^1]  <sup><sub>**`Jan 06, 2026`**<sub></sup>

* Fixed a bug in HTTP port handling in the case of upnext.

#### v2.7.0  <sup><sub>**`Dec 22, 2025`**<sub></sup>

* Updated network call handling to avoid waiting after the HTTP call.
* Updated Device Resolution string.

#### v2.6.5  <sup><sub>**`Dec 12, 2025`**<sub></sup>

* Device & Network Information fixes
* Fixed Player Resolution
* Preload field addition
* App Session Id field addition
* Fix to consider Exit in Buffering

</details>

[^1]: **Performance Report:** [here](https://docs.mediamelon.com/mediamelon/sdk-performance-metrics/roku/roku-sdk-performance-metrics)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mediamelon.com/mediamelon/smartsight-player-sdk-integration/roku/mediamelon-roku-sdk-integration-document.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
