Skip to main content

Heartbeat

Heartbeat is an add-on functionality to the Quickplay Player that facilitates stream concurrency maintenance, maintaining last played position (for VOD) and enforcing geo-restrictions. For Live Streams, Heartbeat can notify the application of all applicable events during the stream.

Setup Heartbeat

Applicability

The corresponding Authorization response for that playback holds the relevant information that indicate whether Heartbeat service is applicable for that playback.

NameDescription
heartbeatFlagIndicates whether heartbeat should be attached for the current playback.
heartbeatFrequencyMsThe recommended heartbeat sync interval in milli-seconds
heartbeatTokenThe unique heartbeat token for the current playback
liveEventTypeThe type of LIVE event i.e. regular or overflow. Applicable exclusively for live events.

HeartbeatConfiguration

HeartbeatConfiguration encapsulates all the necessary information required to enforce Heartbeat. It also holds configurable properties that can be used to tweak the default behaviors.

NameDefault valueDescription
heartbeatEndPointUrl-Heartbeat service end-point url.
streamConcurrencyEndPointUrl-Stream Concurrency service end-point url.
heartbeatSyncIntervalMs60000LThe time interval in seconds used to periodically update stream state of the currently playing content. Default: 60000.
heartbeatMaxAllowedFailures2The maximum number of failed heartbeat check attempts (network or infrastructure issues) that are allowed to happen in line before the Live content's playback is terminated. Default: 2.
recordBookmarkfalseSpecifies whether to use the heartbeat service to record bookmarks/resume points for VOD contents. Default: false.
showPostEventSlateTimeMs900000LThe amount of time - in milliseconds - that the post slate should be displayed for before sending OVERFLOW_EVENT_END. This is applicable only for overflow events. Default: 900000L.
stopPlayerOnStreamTimelineEventtrueIndicates whether the player should automatically be stopped on applicable Stream Timeline Events.
multiStreamModefalseSpecifies whether the client application has initialized multiple playback sessions.
trackViewersCountfalseThe flag indicates whether to track the viewers count or not, for the content to play. Default value is false.
val heartbeatConfiguration = HeartbeatConfiguration(
streamConcurrencyEndPointUrl,
heartbeatEndPointUrl,
heartbeatSyncIntervalMs,
heartbeatMaxAllowedFailures,
recordBookmark,
showPostEventSlateTimeMs,
stopPlayerOnStreamTimelineEvent,
multiStreamMode
)

HeartbeatManager

HeartbeatManager should be attached to a Player by passing the ComposablePlayer instance as a parameter.

NameRequiredDescription
contentIdtrueThe content id for which the heartbeat is to be triggered.
deviceIdtrueThe unique identifier of the device.
heartbeatTokentrueThe unique heartbeat token for the current playback.
heartbeatConfigurationtrueThe HeartbeatConfiguration instance that specifies the Heartbeat service configuration.
platformAuthorizertrueThe PlatformAuthorizer instance to authorize Heartbeat Microservice access.
playertrueThe ComposablePlayer instance that provides PlaybackState information and used to abort the playback in case of errors.
liveStartTimefalseThe start time of the Live event/program in ISO8601 format.
liveEndTimefalseThe end time of the Live event/program in ISO8601 format.
liveEventTypefalseThe type of LIVE stream. This value is part of the payload provided by content authorization service response.
overflowModefalseThe OverflowMode of the overflow LIVE stream. This value is part of the payload provided by content authorization service response.
headersfalseThe optional custom HTTP headers.
loggerfalseThe optional Logger instance.
catalogTypefalseThe value of the Catalog type of content.
primaryContentIdfalseThe unique identifier of the primary content to which the selected content (i.e. secondary angle content) to play is associated with. This is applicable only for multi-camera enabled content.
live360StartTimefalseThe start time of the live 360 camera supported content.
live360EndTimefalseThe end time of the live 360 camera supported content.
val composedPlayer = composablePlayerWith(player)

val heartbeatManager = HeartbeatFactory.createHeartbeatManager(
contentId,
deviceId,
heartbeatToken,
heartbeatConfiguration,
platformAuthorizer,
composedPlayer,
liveStartTime, // applicable only for live streams. part of content authorization response.
liveEndTime, // applicable only for live streams. part of content authorization response.
liveEventType, // applicable only for live streams. part of content authorization response.
overflowMode, // applicable only for live overflow streams. part of content authorization response.
headers, // optional
logger, //optional,
catalogType, // applicable only for multi camera mode
primaryContentId, // applicable only for multi camera mode
live360StartTime, // applicable only for 360 degree camera mode
live360EndTime // applicable only for 360 degree camera mode
)

Track Watch Count

Watch count of the content can be tracked for business purpose. To extend support for Watch Count, additional param should be passed to HeartbeatConfig instance. Along with all necessary information required to enforce Heartbeat, HeartbeatConfig now encapsulates another optional param trackViewersCount to track the watch count of the content.

NameTypeDescription
trackViewersCountBooleanThe flag indicates whether to track the viewers count or not, for the content to play. Default value is false.
val heartbeatConfiguration = HeartbeatConfiguration(
...,
trackViewersCount = true
)

Update Heartbeat token

Quickplay exposes an API to update the heartbeat token so that future heartbeat call will request with the new heartbeat token.

val heartbeatManager = HeartbeatFactory.createHeartbeatManager(
...,
...
)
heartbeatManager.updateHeartbeatToken(<new-token>)

Events during Live Streams

All the applicable events for different type of live streams are part of StreamTimelineEvent and can be notified to the application using Heartbeat. The type of live event is indicated to the application using ContentAuthorizationToken.liveEventType, which is obtained during playback authorization.

NameDescription
LIVE_EVENT_STARTThe start of a one-time Live event.
LIVE_EVENT_ENDThe end of a one-time live event.
LIVE_PROGRAM_STARTThe start of a recurring live program.
LIVE_PROGRAM_ENDThe end of a recurring live program.
OVERFLOW_EVENT_ENDThe end of an overflow event. Applicable only for Overflow events.
BLACKOUTThe playback has blacked out.
OVERFLOW_EVENT_ENDThe end of an overflow event. Applicable only for Overflow events.
BLACKOUTThe playback has blacked out.
LIVE_360_AVAILABLEThe Availability of 360 degree mode
LIVE_360_UNAVAILABLEThe Unavailability of 360 degree mode

Heartbeat relies on liveStartTime, liveEndtime, liveEventType, live360StartTime and live360EndTime passed by the application to send applicable events at the right time.

Listening for StreamTimelineEvents

Heartbeat notifies the application about appropriate StreamTimelineEvents using the Listener attached to the ComposablePlayer that was passed during setup.

override fun onEventReceived(
streamTimelineEvent: StreamTimelineEvent,
suggestedAction: Action,
streamTimelineEventMetadata: StreamTimelineEventMetadata?
) {
// handle events as required
}

Blackouts

While authorizing an asset for Playback, the server might enforce Blackout rules based on tenant specific configuration. When a playback is attempted from a Blacked-out region, the server would respond with the following:

NameDescription
blackoutActionIndicates appropriate action for Blackout scenario. Possible Values: ALLOW, DENY, ALLOW_WITH_UPGRADE.
blackoutUrlThe alternate blackout slate stream to play while the user is in blackout.
note

When receiving a blackoutAction other than ALLOW, the application must play the blackoutUrl instead of the regular contentUrl. BlackoutUrl can be obtained from BlackoutMetadata.

Blackouts are detected and enforced via Heartbeat to ensure when the user is roaming to a blacked-out region, they are no longer able to stream the content. When detecting a blackout, the playback will be aborted and StreamTimelineEvent.BLACKOUT with corresponding Action and BlackoutMetadata(if any) will be propagated to the application via Player.Listener . Application can process the information and manage the blackout based on the UX requirements (typically, swap the on-going player with a player playing blacked-out slate).

Overflow Events

Live events that do not have set start or end times are called Overflow events. These events typically show a pre-slate before the event starts, and dynamically switch to main content when the event eventually starts. Similarly, a post-slate is typically shown after the content has ended.

OverflowMode

Heartbeat uses the OverflowMode to detect when the playback has started i.e. before, during or after the event. This should be provided by the application while setting up Heartbeat.

fun getOverflowMode(): OverflowMode? {
var overflowMode: OverflowMode? = OverflowMode.EVENT
val currentTime = convertToEpochTime(System.currentTimeMillis())
contentAuthorizationToken.liveStartTime?.let { overflowStartTime ->
contentAuthorizationToken.liveEndTime?.let { overflowEndTime ->
overflowMode = when {
currentTime < iso8601UTCDateToEpochTime(overflowStartTime) -> {
OverflowMode.PRE_EVENT
}
currentTime > iso8601UTCDateToEpochTime(overflowEndTime) -> {
OverflowMode.POST_EVENT
}
else -> {
OverflowMode.EVENT
}
}
}
}
return overflowMode
}

fun iso8601UTCDateToEpochTime(iso8601Date: String): Long {
val timeZone = TimeZone.getTimeZone("UTC")
val dateFormat = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'",
Locale.getDefault()
)
dateFormat.timeZone = timeZone
val date = dateFormat.parse(iso8601Date)
return date.time
}

Handling StreamTimelineEvents

Heartbeat notifies the application of all applicable changes in the live stream to ensure that the playback is updated accordingly.

override fun onEventReceived(
streamTimelineEvent: StreamTimelineEvent,
suggestedAction: Action,
streamTimelineMetadata: StreamTimelineMetadata?
) {
when (streamTimelineEvent) {
StreamTimelineEvent.LIVE_EVENT_START -> {
// indicates the main content has started.
// stop pre-slate playback and start the main content playback.
startLiveEvent()
}
StreamTimelineEvent.LIVE_EVENT_END -> {
// indicates the main content has ended.
// stop main content playback and start the post-slate playback.
endLiveEvent()
}
StreamTimelineEvent.OVERFLOW_EVENT_END -> {
// indicates the post-slate has ended after
// honoring HeartbeatConfiguration.showPostEventSlateTimeMs.
// stop post-slate playback and exit.
player.stop()
}
StreamTimelineEvent.LIVE_360_AVAILABLE -> {
// indicates the availability of 360 degree camera mode
}
StreamTimelineEvent.LIVE_360_UNAVAILABLE -> {
// indicates the unavailability of 360 degree camera mode
}
}
}