Heartbeat
Heartbeat is an add-on functionality to the Quickplay Player that facilitates stream concurrency maintenance, maintaining the last played position (for VOD), and enforcing geo-restrictions. For Live Streams, Heartbeat can notify your application of all applicable events during the stream.
Setup Heartbeat
Applicability
The corresponding Authorization response for that playback holds the relevant information that indicates whether the Heartbeat service applies to that playback.
| Name | Description |
|---|---|
| heartbeatFlag | Indicates whether you should attach heartbeat for the current playback. |
| heartbeatFrequencyMs | The recommended heartbeat sync interval in milliseconds |
| heartbeatToken | The unique heartbeat token for the current playback |
| liveEventType | The type of LIVE event (for example, regular or overflow). Applies exclusively to live events. |
HeartbeatConfiguration
HeartbeatConfiguration encapsulates all the necessary information required to enforce Heartbeat. It also holds configurable properties that you can use to tweak
the default behaviors.
| Name | Default value | Description |
|---|---|---|
| heartbeatEndPointUrl | - | Heartbeat service end-point url. |
| streamConcurrencyEndPointUrl | - | Stream Concurrency service end-point url. |
| heartbeatSyncIntervalMs | 60000L | The time interval in seconds used to periodically update stream state of the currently playing content. Default: 60000. |
| heartbeatMaxAllowedFailures | 2 | The 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. |
| recordBookmark | false | Specifies whether to use the heartbeat service to record bookmarks/resume points for VOD contents. Default: false. |
| showPostEventSlateTimeMs | 900000L | The 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. |
| stopPlayerOnStreamTimelineEvent | true | Indicates whether the player should automatically be stopped on applicable Stream Timeline Events. |
| multiStreamMode | false | Specifies whether the client application has initialized multiple playback sessions. |
| trackViewersCount | false | The 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
You should attach HeartbeatManager to a Player by passing the ComposablePlayer instance as a parameter.
| Name | Required | Description |
|---|---|---|
| contentId | true | The content id for which the heartbeat is to be triggered. |
| deviceId | true | The unique identifier of the device. |
| heartbeatToken | true | The unique heartbeat token for the current playback. |
| heartbeatConfiguration | true | The HeartbeatConfiguration instance that specifies the Heartbeat service configuration. |
| platformAuthorizer | true | The PlatformAuthorizer instance to authorize Heartbeat Microservice access. |
| player | true | The ComposablePlayer instance that provides PlaybackState information and used to abort the playback in case of errors. |
| liveStartTime | false | The start time of the Live event/program in ISO8601 format. |
| liveEndTime | false | The end time of the Live event/program in ISO8601 format. |
| programStartTime | false | The currently playing LIVE program start in ISO8601 format. |
| programEndTime | false | The currently playing LIVE program end in ISO8601 format. |
| liveEventType | false | The type of LIVE stream. This value is part of the payload provided by content authorization service response. |
| overflowMode | false | The OverflowMode of the overflow LIVE stream. This value is part of the payload provided by content authorization service response. |
| headers | false | The optional custom HTTP headers. |
| logger | false | The optional Logger instance. |
| catalogType | false | The value of the Catalog type of content. |
| primaryContentId | false | The 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. |
| live360StartTime | false | The start time of the live 360 camera supported content. |
| live360EndTime | false | The 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.
programStartTime, // applicable only for live streams. part of content authorization response.
programEndTime, // 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
You can track the watch count of content for business purposes. To extend support for Watch Count, you should pass an additional param to the 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.
| Name | Type | Description |
|---|---|---|
| trackViewersCount | Boolean | The 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 calls request with the new heartbeat token.
val heartbeatManager = HeartbeatFactory.createHeartbeatManager(
...,
...
)
heartbeatManager.updateHeartbeatToken(<new-token>)
Events during Live Streams
All the applicable events for different types of live streams are part of StreamTimelineEvent and can be notified to your application using Heartbeat.
The type of live event is indicated to your application using ContentAuthorizationToken.liveEventType, which you obtain during playback authorization.
| Name | Description |
|---|---|
| LIVE_EVENT_START | The start of a one-time Live event. |
| LIVE_EVENT_END | The end of a one-time live event. |
| LIVE_PROGRAM_START | The start of a recurring live program. |
| LIVE_PROGRAM_END | The end of a recurring live program. |
| OVERFLOW_EVENT_END | The end of an overflow event. Applicable only for Overflow events. |
| BLACKOUT | The playback has blacked out. |
| OVERFLOW_EVENT_END | The end of an overflow event. Applicable only for Overflow events. |
| BLACKOUT | The playback has blacked out. |
| LIVE_360_AVAILABLE | The Availability of 360 degree mode |
| LIVE_360_UNAVAILABLE | The Unavailability of 360 degree mode |
Heartbeat relies on liveStartTime, liveEndtime, liveEventType, live360StartTime, and live360EndTime that you pass to send applicable events at the right time.
Listen for StreamTimelineEvents
Heartbeat notifies your application about appropriate StreamTimelineEvents using the Listener attached to the ComposablePlayer that you 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 you attempt playback from a blacked-out region, the server responds with the following:
| Name | Description |
|---|---|
| blackoutAction | Indicates appropriate action for Blackout scenario. Possible Values: ALLOW, DENY, ALLOW_WITH_UPGRADE. |
| blackoutUrl | The alternate blackout slate stream to play while the user is in blackout. |
When you receive a blackoutAction other than ALLOW, you must play the blackoutUrl instead of the regular contentUrl. You can
obtain BlackoutUrl from BlackoutMetadata.
Blackouts are detected and enforced via Heartbeat to ensure that when you're roaming to a blacked-out region, you're no longer able to stream the content.
When detecting a blackout, the playback is aborted and StreamTimelineEvent.BLACKOUT with corresponding Action and BlackoutMetadata (if any) is
propagated to your application via Player.Listener. You can process the information and manage the blackout based on the UX requirements (typically,
swap the ongoing player with a player playing blacked-out slate).
Overflow Events
Live events that don't 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 ends.
OverflowMode
Heartbeat uses the OverflowMode to detect when the playback has started (that is, before, during, or after the event). You should provide this 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
}
Handle StreamTimelineEvents
Heartbeat notifies your application of all applicable changes in the live stream to ensure that you update the playback 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
}
}
}