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:
- using the
LOAD
message interceptor in your Web Receiver application. (recommended) - 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 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
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
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:
- Set Stream Type - Mark the stream as being a live stream.
- Add Program Guide Data - Set a start time
and duration in the
MediaMetadata
object. - 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
.