Skip to main content

Server Side Ad Insertion using FLBrightcove

The fl-player-ads-brightcove library enables the playback of Brightcove-curated streams with advertisements. To build a Brightcove player, use the BrightcoveAdsPlayerBuilder() API with the following properties:

PropertyTypeDescription
vmapURLStringSets the URL to remote VMAP document that contains ads cue point metadata.
adPlaybackPolicyAdPlaybackPolicySets the [AdPlaybackPolicy] instance that specifies the policy rules for Brightcove ads handling.
playbackPolicyHandlerPlaybackPolicyHandlerSets the [PlaybackPolicyHandler] instance that enforces the policy rules related to the content with Brightcove ads.
playbackPolicyHandlerListenerPlaybackPolicyHandler.ListenerSets the [PlaybackPolicyHandler.Listener] instance that provides the notification for ad playback policy related events.
palConfigurationPALConfigurationSets the [PALConfiguration] instance that is used in the [PALSession] initialization. Optionally sets the permission to store user data like cookies, device IDs, and advertising IDs when using [PALSession] calls.
dataCollectionConfigBrightcoveDataCollectionConfigEnables Brightcove Data Collection API v2 reporting.
note

The client application may optionally provide custom AdPlaybackPolicy and PlaybackPolicyHandler implementation, and also a PALConfiguration instance as BrightcoveAdsPlayerBuilder properties.

Brightcove player creation use cases

The following use cases are supported by BrightcoveAdsPlayerBuilder for BrightcovePlayer instance creation:

  1. The application provides VMAP URL and PAL configuration and optionally other builder properties but not media URL.
  2. The application provides VMAP URL and optionally other builder properties but not PAL configuration and media URL.
  3. The application provides media URL and PAL configuration and optionally other builder properties but not VMAP URL.
  4. The application provides media URL and optionally other builder properties but not VMAP URL and PAL configuration.

Create Brightcove player

Build a Player using BrightcoveAdsPlayerBuilder as an extension of PlayerBuilder (see the Brightcove Player Creation Use Cases section).

val brightcovePlayerBuilder = BrightcoveAdsPlayerBuilder()
brightcovePlayerBuilder.mediaType(MediaType.HLS)
brightcovePlayerBuilder.vmapURL(vmapURL)
brightcovePlayerBuilder.playbackPolicyHandlerListener(policyHandlerListener)
val context: Context = getApplication()
coroutineScope.launch {
when (val result: Result<BrightcovePlayer?, Error?> =
brightcovePlayerBuilder.buildAsync(
context
)
) {
is Result.Success -> {
val brightcovePlayer = result.value
brightcovePlayer?.let { adsPlayer ->
adsPlayer.addListener(playerListener)
adsPlayer.addAuxiliaryListener(playerAuxiliaryListener)
adsPlayer.registerAdListener(adListener)
bookmarkPositionMs?.let { bookmark ->
adsPlayer.playbackProperties.initialStartTimeMs = bookmark
}
adsPlayer.play()
}
}
is Result.Failure -> {// If the `BrightcoveAdsPlayerBuilder.buildAsync(context)` invocation fails with an `Error` this condition, most likely, is the result of the VMAP file download or parsing failure.
// handle error
}
}
}
note

The PlayerBuilder build function is deprecated and MUST not be used. Only use buildAsync. This function is declared as a suspend function and MUST be called using a CoroutineScope builder function (for example, using the launch extension function).

Once you successfully build the BrightcovePlayer instance, you may optionally retrieve the preview image files metadata, if available, using the thumbnails property of the BrightcovePlayer instance. If you decide to use the preview image files metadata directly, you're responsible for downloading and decoding the preview images based on the current player playhead position. BrightcovePlayer provides another API to retrieve a preview image URL for a given player playhead position - getThumbnailUrl(positionMs: Long).

player?.getThumbnailPreview(position) { preview ->
logger.trace { "Got thumbnail bitmap: $preview" }
}

Brightcove Data Collection API v2

Brightcove requires clients who use a third-party player (instead of the Brightcove player) to report playback data via the Data Collection API v2. This integration satisfies that requirement while keeping the QuickPlay Player in place.

Automatically Tracked Events

#EventWhen
1player_loadSession starts (startSession() called)
2video_impressionPlayer state reaches LOADED
3play_requestPlayer state reaches LOADING
4video_viewFirst STARTED state outside an ad break
5video_engagementPeriodically during playback (default every 10 s)
6ad_mode_beginAd break begins
7ad_mode_completeAd break ends
8errorPlayback error occurs

BrightcoveDataCollectionConfig Reference

FieldRequiredDefaultDescription
accountIdYesBrightcove account ID
videoIdYesBrightcove video ID
videoNameNoHuman-readable name of the video
sessionIdNoauto UUIDPer-session identifier
engagementEventIntervalNo10000The interval (ms) between video_engagement beacons has an upper bound of 20000ms. If a higher value is set, it will be reset to the default of 10,000ms.
userIdNoUnique user identifier
deviceTypeNonulle.g. "mobile", "tv"
deviceOsNonulle.g. "android"
deviceOsVersionNonullOS version string
deviceManufacturerNonullDevice manufacturer
deviceModelNonullDevice model name
countryNonullISO 3166-1 alpha-2 country code
countryNameNonullHuman-readable country name
regionNonullRegion / state code
regionNameNonullHuman-readable region name
cityNonullCity name
dmaNonullNielsen DMA code
destinationNonullCurrent page URL / deep-link destination
sourceNonullReferring page URL / source
playerIdNonullPlayer identifier sent to Brightcove
playerNameNonullHuman-readable player name
applicationNonullCustom application identifie
debugLoggingNofalseLog all outgoing beacon URLs
includeQoEMetricsNofalseInclude bitrate/resolution/dropped-frames in engagement beacons. Disable on low-end Smart TV devices.
import com.quickplay.vstb7.player.ad.brightcove.datacollection.BrightcoveDataCollectionConfig

// 1. Build a config (only accountId and videoId are required)
val dataCollectionConfig = BrightcoveDataCollectionConfig(
accountId = 12345, // Numeric Brightcove account ID
videoId = "your-brightcove-video-id",
)
brightcoveAdsPlayer?.dataCollectionConfig(dataCollectionConfig)

Listen to ad events

You can register an AdEventListener instance with AdComposedPlayer for listening to Ad Events. The following ad events are triggered by AdEventListener callbacks:

  1. Cue Point availability (available only after obtaining a response from Ad Server)
  2. Ad Break Start called when the first Ad, in an Ad Break, have started playing. This event may also provide AdBreakInfo metadata for the active Ad Break.
  3. Ad Start called when an Ad has started playing. This event will also provide AdInfo metadata for the active Ad.
  4. Ad Playback Progress called during Ad Break playback when the Ad's progress is updated. This event will also provide AdProgressInfo metadata for the active Ad Break.
  5. Ad End called when an Ad has finished playing. This event will also provide AdInfo metadata for the active Ad.
  6. Ad Break End called when all the Ads, in an Ad Break, have finished playing. This event may also provide AdBreakInfo metadata for the active Ad Break.
  7. Ad Error called when an error has been encountered during Ads playback. This event will also provide Error metadata for the active Ad.
  8. Ad Tracking Event called when an ad tracking event sucha as ad's first quartile, midpoint, third quartile etc. is triggered. This event will also provide AdTrackingEvent metadata for the active Ad Break or Ad.
val adEventListener = object : AdEventListener {
override fun onAdCuePointsAvailable(cuePoints: LongArray) {
logger.info { "cue_points_available" }
}
override fun onAdBreakStart(adBreakInfo: AdBreakInfo?) {
logger.info { "ad_break_start" }
}
override fun onAdStart(adInfo: AdInfo) {
logger.info { "ad_start" }
}
override fun onAdPlaybackProgress(adProgresInfo: AdProgressInfo) {
logger.info { "ad_progress" }
}
override fun onAdEnd(adInfo: AdInfo) {
logger.info { "ad_end" }
}
override fun onAdBreakEnd(adBreakInfo: AdBreakInfo?) {
logger.info { "ad_break_end" }
}
}
adsPlayer.registerAdListener(adEventListener)

Ad Metadata

AdInfo

Represents an advert object.

PropertyTypeDescription
adIDstringThe identifier of the advert
sequencenumberThe sequence of the advert
adStartTimeOffsetMsnumberThe start playhead position of the advert in milliseconds
durationMsnumberThe duration of the advert in milliseconds
remainingTimeMsnumberReturns the natural playback time remaining for the advert in milliseconds
isSkippablebooleanIndicates if the ad is skippable
skipOffsetMsnumberThe value of skip offset for the advert, in milliseconds. If the VAST skip offset is not defined then this method returns -1, signifying that the advert cannot be skipped.
isFillerbooleanWhether this advert represents filler content
adBreakInfoAdBreakInfoThe ad break in which the advert belongs in
adVastPropertiesAdVastPropertiesRepresents a VAST properties of this advert.
AdBreakInfo

Represents an ad break object.

PropertyTypeDescription
adBreakIDStringUnique id of the ad break
contentTimePositionAdContentTimePositionThe position of the ad break, can be on of preroll, midroll or postroll
adSequencePositionIntThe sequence position of the ad within the ad break.
adBreakStartTimeOffsetMsDoubleThe content time offset at which the current ad break was scheduled
remainingTimeMsDoubleThe natural playback time remaining for the ad break in milliseconds
durationMsDoubleThe maximum duration of the ad break in milliseconds.
totalAdsIntThe total number of ads contained within this ad break.
adBreakIndexIntThe index of the current ad break
note

The totalAds read from AdPlayer may not be accurate when it comes from onAdStart event. This may change once ad playback starts. GoogleIMA advises to read totalAds on or after FIRST_QUARTILE ad tracking event, to get a reliable data.