Roku SceneGraph Integration Guide

Integrate the StreamLayer Roku SDK into a SceneGraph app with initialization, video player attachment, event sessions, pause ads, overlay visibility, and focus handling.

Overview

This guide walks through the full integration process: initializing the SDK, attaching it to your video playback, managing event sessions, configuring pause ads, observing overlay visibility, and handling focus.

The SDK integrates directly with Roku SceneGraph video playback and handles StreamLayer Element rendering, lifecycle management, and analytics.


Sample Integration Project

A complete working sample Roku application is available in our repository:

https://github.com/StreamLayer/roku-sdk-sample

The sample demonstrates:

  • SDK initialization
  • Dynamic SDK package loading via sdkUri
  • Video player attachment
  • Event session switching
  • Pause ad integration (Native + VAST)
  • Overlay visibility events
  • Focus management
  • SceneGraph overlay rendering

The repository includes a reusable SLSDK module containing:

  • SLView — public-facing component used by the Roku application
  • SLManager — internal controller responsible for the SDK lifecycle
  • StreamLayerSDK.pkg — the StreamLayer UI bundle

The SLSDK folder is fully self-contained and can be copied directly into any Roku channel to enable StreamLayer integration.


Adding the StreamLayer SDK to Your Roku Project

The StreamLayer UI bundle is distributed as a .pkg component library. Add it to your Roku project under:

shared/
└── StreamLayerSDK.pkg

Reference it in your SceneGraph XML:

<Library
    id="SLSDKLibrary"
    uri="pkg:/shared/StreamLayerSDK.pkg" />

SDK Initialization

Before StreamLayer can render StreamLayer Elements, you must initialize the SDK.

The initialization process performs the following steps:

  • Loads the StreamLayer SDK library from the provided sdkUri
  • Creates the internal StreamLayer root node
  • Attaches the provided video player reference
  • Initializes and starts the StreamLayer rendering engine
  • Optionally enables logging, analytics, and ad-specific behavior based on configuration flags

initialize(params)

Call the initialize function on your SLView component:

m.slView.callFunc("initialize", {
    apiKey: "YOUR_API_KEY",
    playerRef: m.videoPlayer,
    sdkUri: "YOUR_SDK_URI",
    isLoggingEnabled: true,
    isAnalyticsEnabled: true,
    isVastModeEnabled: false,
    isPrefetchEnabled: false
})

Parameters:

apiKey

StreamLayer API key used for authentication.


playerRef

Reference to your SceneGraph Video node.


sdkUri

Location of the StreamLayer SDK package.

Example: pkg:/shared/StreamLayerSDK.pkg

Notes: CDN delivery may be available. Contact StreamLayer for access.


isLoggingEnabled

Enables SDK debug logging.

Default: false


isAnalyticsEnabled

Enables analytics event reporting.

Default: false


isVastModeEnabled

Enables external VAST pause ad mode.

Default: false

When enabled:

  • Host provides VAST XML URL
  • SDK renders pause ads

isPrefetchEnabled

Enables pause ad prefetch caching.

  • Default: false
  • When enabled:

SDK may preload pause ads

Reduces pause ad load latency

Effective with VAST mode


Attaching the Video Player

StreamLayer requires a reference to your Roku video node so that StreamLayer Elements synchronize correctly with playback.

Supported video nodes include:

  • Video

Attach the player:

slView.attachPlayer(m.videoPlayer)

StreamLayer uses this reference to:

  • coordinate StreamLayer Element timing
  • manage UI focus
  • adjust layout around your video player

Managing Event Sessions

Notify StreamLayer when playback switches content:

slView.setEvent("event_id_here")

This updates all event-specific content, including:

  • interactive StreamLayer Elements
  • ads configured for that event

You can call this multiple times during playback.


StreamLayer Element Visibility Events

The following read-only fields expose the current visibility state of StreamLayer StreamLayer Elements. These fields can be observed to synchronize host UI behavior with SDK StreamLayer Element state.

Promo Visibility

Indicates whether a promo StreamLayer Element is currently visible.

m.slView.observeField("isPromoVisible", "onPromoVisibleChanged")

Notification Visibility

Indicates whether a notification StreamLayer Element is currently visible.

m.slView.observeField("isNotificationVisible", "onNotificationVisibleChanged")

Pause Ad Visibility

Indicates whether a pause ad StreamLayer Element is currently visible.

m.slView.observeField("isPauseAdVisible", "onPauseAdVisibleChanged")


Pause Ad Integration

Native StreamLayer Pause Ads

If isVastModeEnabled = false:

SDK handles ad loading and rendering.

slView.showPauseAd()

External VAST Pause Ads

If isVastModeEnabled = true:

slView.showPauseAd(vastUrl)

Host provides VAST XML URL. SDK handles rendering and lifecycle.


Runtime Mode Switching

Pause ad mode can be changed at runtime.

slView.setVastModeEnabled(true)

Notes:

  • Safe during playback
  • Applies to next pause ad request
  • Does not affect active pause ad

Cleaning Up the SDK

If you want to clean up the SDK and remove the StreamLayer view from your scene, you can dispose it:

slView.disposeSdk()

This will:

  • remove the StreamLayer node from your UI
  • clear all StreamLayer Element components
  • unregister all internal SDK listeners

⚠️ Important: After disposing the SDK, it becomes fully inactive. If your application returns to a StreamLayer-enabled playback screen, you must call initialize() again.


Focus Handling

StreamLayer uses standard Roku focus rules for interactive elements like ads, trivia, and predictions.

To give StreamLayer focus:

slView.focus = true

To return focus to your application:

slView.focus = false


Prefetch Behavior Notes

Prefetch enables preloading and temporary caching of pause ads before they are needed, reducing the time required to display an ad when playback is paused.

Notes:

  • Prefetch is primarily used when external VAST ad delivery is enabled.
  • Prefetch is optional and can be enabled based on integration needs.
  • Prefetched ads are stored in memory with a 50-minute TTL.
  • On get(), stale entries are automatically evicted before returning.
  • If the cache has a valid (non-expired) ad, it is returned immediately (cache HIT); otherwise a new fetch is triggered (cache MISS).