Live Streaming

The Cast SDK includes built-in APIs for supporting live content. This includes a flexible, out-of-box UI, coupled with APIs that allow developers to create rich live experiences with just a few lines of code. The Live API supports displaying start and end times, program metadata, DVR controls, and seekable windows.

This guide demonstrates how to configure a stream to the Live APIs, including code and metadata samples for configuring core Live scenarios, along with screenshots demonstrating what each scenario looks like.

Prerequisites

Familiarity with the basics of implementing a Web Receiver is required before reviewing this guide. Additionally, to run the code samples you will need access to a live stream that conforms to one of the supported media types for Cast. In general, the Live feature supports typical live stream configurations for the supported media.

The following terms are used throughout the guide:

  • Seekable Window - The range of a live stream that users can seek within.
  • Live Edge - The newest part of a live stream available to the player.
  • Play Head - A UI timestamp for the current playback position.

Casting a live stream

There are two ways to configure the Web Receiver SDK to use the Live API for content:

  1. using the LOAD message interceptor in your Web Receiver application. (recommended)
  2. using a sender-side or receiver-side generated load request.

The interceptor provides a LoadRequestData object that contains all the important metadata about a load request. To indicate a load request is for a live stream, simply set the streamType on the mediaInformation object to StreamType.LIVE. MediaInformation.duration should be -1 as the player instances are responsible for calculating it when the content is LIVE.

/*
* This interceptor is called before your content is loaded by a Cast device
*/
playerManager.setMessageInterceptor(
   cast.framework.messages.MessageType.LOAD,
   request => { /* cast.framework.messages.LoadRequestData */
       request.media.streamType = cast.framework.messages.StreamType.LIVE;
   return request;
});

Adding program guide data

Live streams, especially long running streams like a TV channel, are able to display on-screen guide/programming metadata based off the current playback position in a live stream. Content providers are strongly encouraged to include programming metadata in their Web Receiver applications for a better end user experience.

You can configure the initial guide data for a stream in the LOAD message interceptor, the same way we indicated the stream was a live stream in the previous example. Individual sections or programs in the live stream are represented as MediaMetadata objects which are then stored in a queue. There is a different MediaMetadata class for different types of programs—e.g. TvShowMediaMetadata, MovieMediaMetadata, MusicTrackMediaMetadata, etc.

In the following code snippet, we use the MediaMetadata object to specify the start time of each show with a UNIX Timestamp with the sectionStartAbsoluteTime property. The duration of a program is represented in seconds.

// The metadata for a single TV show
const currentShow = new cast.framework.messages.TvShowMediaMetadata();
currentShow.episode = 15;
currentShow.seriesTitle = 'The Odyssey';
currentShow.title = 'Scylla and Charybdis';
currentShow.sectionStartAbsoluteTime = toUnixTimestamp('9:00 PM');
currentShow.sectionDuration = HOUR_IN_SECONDS;

const previousShow = new ...;
const nextShow = new ...;

const containerMetadata = new cast.framework.messages.ContainerMetadata();
containerMetadata.title = 'My TV Channel';
containerMetadata.sections = [previousShow, currentShow, nextShow];

playerManager.getQueueManager().setContainerMetadata(containerMetadata);

Live seekable range

The Cast SDK includes UI elements and controls that allow a user to move their playhead within the stream using the Expanded Controller or touch controls on devices that are touch-enabled.

The LiveSeekableRange represents the range of time in a stream where a user is able to seek. On the Web Receiver you can access information about the seekable range via PlayerManager.getLiveSeekableRange(), which returns a LiveSeekableRange object. The main properties on the object to be aware of are:

  • start — the start time (in seconds) of the range relative to the beginning of the stream in seconds.
  • end — the maximum possible time (in seconds) the player can seek to, based on available segments, relative to the beginning of the stream.
  • isMovingWindow — a boolean value that indicates if the seekable range moves (i.e. older segments are removed from the manifest) with the stream, this should be true for all live streams.
  • isLiveDone — a boolean value that indicates if the live stream has finished, meaning that no new segments are being generated.

The size of the seekable range, represented as the time between start and end, is determined by the number of segments available in the stream and will move with the stream. For example, if, at the start of the stream, the seekable range is {start:0, end: 600, isMovingWindow: false, isLiveDone: false}, ten seconds after the stream starts it can become {start: 10, end: 610, isMovingWindow: true, isLiveDone: false}. It is important to note the start and end times in the seekable range are updated based on the time it takes to generate a new segment. Thus if the typical length of a segment for your stream is 10 seconds, the start and end times will be updated about every 10 seconds as well.

Disable seeking

To disable seeking within a stream, you need to remove the seek functionality from the supported media commands on the Web Receiver:

// disable seeking in the LOAD messageInterceptor
playerManager.removeSupportedMediaCommands(cast.framework.messages.Command.SEEK, true);

Removing the supported media command for SEEK signals to sender applications and touch displays to disable seeking, but doesn't disable voice commands such as ‘Ok google, seek backwards 30 seconds.’ See the supported media commands with voice guide for details about how to disable media commands for voice.

Live framework events

Two events, LIVE_ENDED and LIVE_IS_MOVING_WINDOW_CHANGED, are included in the Live API. Both events are passed a LiveStatusEvent object, which contains the current live seekable range.

Event Description
LIVE_ENDED Triggered when a live stream ends. At this point the end value in the LiveSeekableRange will stop updating; users will still be able to view content within the live seekable range.
LIVE_IS_MOVING_WINDOW_CHANGED Triggered when the seekable range of a live stream changes from a fixed window to a moving window, or vice versa. For a live stream this will happen when the player detects the manifest is removing earlier segments.

Live stream scenarios

There are eight possible types of scenarios for live streaming, each of which are configured by setting three core settings:

  • Stream has a start time
  • Stream has an end time
  • Users are allowed to seek within the live stream's seekable window

See Adding Program Guide Data for how to configure those values.

Below are descriptions and screenshots of the scenarios supported by the Live API. The variables T1 and T2 are used to represent the timestamp on the left and right of the UI respectively.

Start time End time Seekable T1 T2
Scenario 1 No No No Play Head Not Shown
Scenario 2 No No Yes Play Head Not Shown
Scenario 3 No Yes No Play Head Not Shown
Scenario 4 No Yes Yes Play Head Not Shown
Scenario 5 Yes No No Show Start TIme Play Head
Scenario 6 Yes No Yes Show Start TIme Play Head
Scenario 7 Yes Yes No Show Start Time Show End Time
Scenario 8 Yes Yes Yes Show Start Time Show End Time

Scenario one

Start time End time Seekable T1 T2
No No No Play head Not Shown

Scenario one has no start or end time and users are unable to seek within the stream. When a user stops a stream, playback will resume from live edge instead of where the stream was paused.

Scenario seven

A TV Showing Chromecast's Live UI for Scenario 7 with Clock Time A mobile phone showing the Live UI for Scenario 7 with Clock Time

Start time End time Seekable T1 T2
Yes Yes No Play Head Program Duration

Scenario seven has a start time and end time but is not seekable. The two timestamps in the UI, T1 and T2, represent the current playhead time and total program duration respectively. If a user pauses/resumes playback the stream will resume at the live edge of the stream. In the above example, the red section of the seek bar represents the portion of the stream since the user started watching.

Scenario eight

A TV Showing Chromecast's Live UI for Scenario 8 with Clock Time A mobile phone showing the Live UI for Scenario 8 with Clock Time

Start time End time Seekable T1 T2
Yes Yes Yes Play Head Program Duration

Scenario seven has a start time, end time, and is seekable. The two timestamps in the UI, T1 and T2, represent the current playhead time and total program duration respectively. If a user pauses/resumes playback the stream will resume at the time they paused if it is within the seekable window—the area in red on the seek bar represents where a user can seek back to and the area in white represents where they can seek forward to.

Configuring a scenario

Configuring a stream as a specific Live Scenario is done in three parts:

  1. Set Stream Type - Mark the stream as being a live stream.
  2. Add Program Guide Data - Set a start time and duration in the MediaMetadata object.
  3. Configure Seek Functionality - Enable or disable seeking.

Playback behavior

While paused, the UI will continue to have its playback metadata updated—this includes playback head and live edge times. Upon resumption of the stream, there are a few behaviors to be aware of that vary based on the stream configuration.

Seekable streams

Upon resumption of a seekable stream:

  • The live edge shall be updated to the live location and the seekable range will be adjusted accordingly.
  • If the playhead jumps past the current show, the scrub bar will be updated with the metadata from the new show (including start time and end time if available).
  • If a seekable window has length 'X', the seekable range will extend back to at most 'X', or to the beginning of the show, whichever is smaller.
  • If the user was paused long enough so that the current time is no longer in the seekable window, the stream will resume at the earliest point (far left) of the seekable window.

Seek to LiveSeekableRange.end to resume playback at the live edge after unpausing.

let playerManager = cast.framework.CastReceiverContext.getInstance().getPlayerManager();
// Intercept the message to PLAY
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.PLAY, (requestData) => {
  ...
  if (playerManager.getLiveSeekableRange()) {
    // Resume playback at the live edge
    playerManager.seek(playerManager.getLiveSeekableRange().end);
  } else {
    return requestData;
  }
  ...
});

Non-seekable streams

Upon resumption of a non-seekable stream:

  • In this case, playback will resume at the live edge.
  • If the live edge jumps past the current show, the scrub bar should be updated with the metadata from the new show (including start time and end time if available).

API surface changes & customizing Live UI

The Cast SDK has built-in support for creating custom user interfaces instead of using the out-of-the-box UI. However it is important to follow the Cast UX Design Checklist when customizing the interface.

Web Receiver

On the Web Receiver, the PlayerData includes the following fields to allow developers to extend their custom interfaces for live streams:

  • isLive - a flag that indicates if the current stream is a live stream, as opposed to VOD.
  • liveSeekableRange - the seekable range to be shown on screen demarcating the DVR window.
  • mediaStartAbsoluteTime - when the section started in absolute time (UNIX Epoch).
  • sectionStartTimeInMedia - section start time in seconds relative to the media start time.
  • sectionDuration - section duration in seconds.

Also make sure to take into account the two live events when customizing the UI.

Android SDK

As part of the Live functionality, the use of the Android Seekbar Widget in the UIMediaController has been deprecated, instead use the CastSeekBar.