Video Playback

The Cloud Solution relays video URLs from the app to be played on the Roku native video player.

You.i React Native Apps

For You.i React Native apps, video playback is triggered with the play() method of the Video or VideoRef components.

The props accept any type of values. The following are a few examples:

  • Simple properties without URL and stream format, to be provided with CYIAbstractVideoPlayer::Prepare:

     {
       notificationinterval: 3
     }
    
  • Simple properties with url and stream format, which will ignore the arguments of CYIAbstractVideoPlayer::Prepare:

     {
       content: {
         url: "http://link.theplatform.com/s/BpkrRC/ckSTzzdGO_K3",
         streamformat: "hls"
       }
     }
    
  • More content properties without URL and stream format, to be provided with CYIAbstractVideoPlayer::Prepare:

     {
       content: {
         id: "abcdefg",
         contenttype: "movie",
         closedcaptures: true,
         length: 600,
         hdbranded: true,
         ishd: true,
         live: false,
         title: "Sample Video"
       },
       notificationinterval: 3,
       surface: {
         handlebackkeyevent: false,
         exitonvideocomplete: false,
         shouldautofocus: false,
       },
       analytics: {
         conviva: {
           convivainfo: {
             streamurl: "http://link.theplatform.com/s/BpkrRC/ckSTzzdGO_K3",
             islive: false,
             viewerid: "CloudTester",
             playername: "Roku"
           },
           convivatag: {
             assetid: "ckSTzzdGO_K3",
             videotype: "VOD",
             streamprotocol: "HLS"
           },
           assetname: "Big Bug Bunny"
         }
       },
       ads: {
         rokuads: {
           length: 500,
           contentid: "movies",
           genre: "General Variety"
           adurl: "... ad url ..."
         }
       }
     }
    

Specifying the Notification Interval

By default, notifications are generated every 0.5 seconds. You can change that setting by using the notificationinterval key in the video node properties.

{
  notificationinterval: 3
}

C++ Apps

For C++ apps, video playback is triggered by calling Play() on the C++ app’s CYIAbstractVideoPlayer. (A custom Roku-cloud player object is instantiated by CYIDefaultVideoPlayerFactory when the application is linked against the cloud library.)

This action sends playVideoCommand to the Roku client with the video URL, any set video metadata, and the scene node on which to play the video.

The parent-child relationships of the video player components are as follows:

  • <VideoSurface>: Cloud custom component (VideoSurface.xml stored server-side). Exported if CYIVideoSurfaceView is present in the scene. Present in the component library and referenced in CloudYouiLib.xml).
  • <VideoPlayer>: Cloud custom component (VideoPlayer.xml stored client-side). Created as a child of the <VideoSurface> in main.brs in response to playVideoCommand. Owns the playerTask which is also instantiated in main.brs, based on the ads object’s playerTaskName field.
  • <Video>: Roku Component, the video node.

Video Node Properties

A Roku Cloud Solution application provides a set of Roku video node properties to play videos on the Roku client. These properties are:

For C++ applications, you can call the SetVideoNodeProperties API of the cloud interface with a parameter of CYIBundle that contains the video and content video node properties. The values in CYIBundle are of the CYIAny type. The types in the CYIAny, string type must always be in the CYIString type, and nested objects should always be in the CYIAny(std::map<CYIString, CYIAny>) type. Here are some examples:

{
  content: {
    id: "abcdefg",
    contenttype: "movie",
    closedcaptures: true,
    length: 600,
    hdbranded: true,
    ishd: true,
    live: false,
    title: "Sample Video"
  }
}

Specifying the Notification Interval

By default, notifications are generated every 0.5 seconds. You can change that setting by using the notificationinterval key in the video node properties; for example:

{
  notificationinterval: 3
}

Exit on Video Complete

By default, the Cloud Solution assumes that video playback is a full-screen experience and the user is automatically navigated back once video completes.

However this automatic navigation back can be disabled by adding the exitonvideocomplete: false to the surface object; for example:

surface: {
  handlebackkeyevent: false,
  exitonvideocomplete: false,
  shouldautofocus: false,
}

If your application disables exit on playback complete, you are responsible for managing the scene; for example focus, view presentation, and so on. For C++ applications, you can manage the scene by calling the SetVideoSurfaceProperties API of the Cloud interface with a parameter of CYIBundle that contains the video surface properties. For example:

// Set up video surface props
CYIBundle videoSurfaceProps;
videoSurfaceProps.Put("handlebackkeyevent", false);
videoSurfaceProps.Put("exitonvideocomplete", false);
CYICloud::GetInterface().SetVideoSurfaceProperties(videoSurfaceProps);

Get an Alert when Video Playback is Complete

Regardless of whether exitonvideocomplete is set, the Roku client issues a videocomplete event when playback has finished. Your application can capture and process this event by registering a lambda function as an event listener. We recommend that you register for the specific videocomplete event as shown below, although you can also register a generic listener for all events by passing in CYIString::EmptyString() as the first argument to RegisterDataListener.

// Register your listener
m_videoCompleteHandlerId = CYICloud::GetInterface().RegisterDataListener("videocomplete", [this](CYIString eventId, const yi::rapidjson::Document *pEvent) {
    this->PlayNextVideo();
    return true;
});

After catching the videocomplete event, your function takes whatever actions are needed, then returns true if you’ve completely resolved that event, or false if you’d like the event to be passed to any registered generic event handlers.

Your application must also unregister its listener when you’re done with video playback. Failure to do so could result in a crash if further events of this type are triggered and your listener isn’t available to receive them.

//Unregister your listener
CYICloud::GetInterface().UnregisterDataListener("videocomplete", m_videoCompleteHandlerId);

Alternate Player Calling Sequence

Typically, an app exports the player screen which includes the video player and surface node. The app then sends a PLAY command with the surface node name to the Roku client, as shown in the following figure:

Image

In the previous sequence, scene export and player instantiation are processed sequentially. In some cases however, the resulting time needed to reach the playable state may be too long to meet Roku certification requirements.

To reduce the time to reach the playable state, you can change the calling sequence so that scene export and player instantiation happen simultaneously, as shown in the following figure:

Image

In this alternate sequence, player instantiation happens first. The player node on Roku is created with control: "prebuffer" and, as a result, video buffering can begin immediately. Actual playback begins with control: "play" after the scene is exported and the player node is attached to the surface node.

This alternate sequence can reduce the time needed to export the scene and get the player ready by up to a few seconds depending on the complexity of the player screen scene, the playback back-end server, and network circumstances.

Roku Native Base Index Frame Display Support

As part of Roku certification requirements, apps should display Base Index Frame (BIF) images whenever a user scrubs the timeline bar. The Roku platform supports two types of trick-play modes: time-based trick-play and scene-based trick-play. A scene-based trick mode is based on the availability of scene information in the form of BIF files, or standard thumbnail files for HLS or DASH.

The BIF information, which is part of the VideoNode and ContentNode, is provided also with the VideoNodeProperties.

  • VideoNode has the bifdisplay field with the BifDisplay content node to define a few properties. See Provide Video Node Properties for more details.
  • The Content field of the video node has the fields for the HD BIF url and the SD BIF URL.

For C++ Apps

const auto url = CYIUrl("http://video.ted.com/talks/podcast/DanGilbert_2004_480.mp4");
const auto format = CYIAbstractVideoPlayer::StreamingFormat::MP4;
const CYIString expectedSdBifUrl = "https://image.roku.com/ZHZscHItc2Ft/thumbnails/simplevideo-with-bif/video-sd.bif";
const CYIString expectedHdBifUrl = "https://image.roku.com/ZHZscHItc2Ft/thumbnails/simplevideo-with-bif/video-hd.bif";

std::map<CYIString, CYIAny> content = {
    {"sdbifurl", expectedSdBifUrl},
    {"hdbifurl", expectedHdBifUrl}};
std::map<CYIString, CYIAny> bifDisplay = {
    {"framebgblendcolor", CYIString("#FF0000FF")}};
CYIBundle properties;
properties.Put("content", CYIAny(content));
properties.Put("bifdisplay", CYIAny(bifDisplay));

m_pPlayer->Prepare(url, format);
EXPECT_TRUE(CYICloud::GetInterface().SetVideoNodeProperties(properties));

For React Native Apps

metadata: {
  content: {
    sdbifurl: "https://image.roku.com/ZHZscHItc2Ft/thumbnails/simplevideo-with-bif/video-sd.bif",
    hdbifurl: "https://image.roku.com/ZHZscHItc2Ft/thumbnails/simplevideo-with-bif/video-hd.bif"
  },
  bifdisplay: {
    framebgblendcolor: "#FF0000FF"
  }
}

Roku Voice Control Support

Voice controls enable applications to handle commands from the Roku voice remote and Roku mobile app. By default, all applications support the basic voice controls without any additional configuration, such as “fast forward”, “rewind”, “pause”, “resume”, and “replay”. To support enhanced voice controls, such as “seek”, “start over”, and “next”, the features have to be enabled by adding the following flags to the manifest file:

  • supports_etc_seek=1: for “seek” and “start over”
  • supports_etc_next=1: for “next”

For details on voice control, see the Roku article Implementing voice controls.