-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8706a48
commit 7713e33
Showing
2 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
theoplayer/how-to-guides/01-ads/13-custom-ssai-integration.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# Custom Server Side Ad Insertion | ||
|
||
THEOplayer provides a way to integrate with third-party advertisement providers, | ||
and have them report their ads and ad-related events through the THEOplayer APIs. | ||
|
||
## Android SDK | ||
|
||
### Prerequisites | ||
|
||
Your THEOplayer SDK needs to be on version 7.6.0 or higher. | ||
|
||
### Integration ID | ||
|
||
To make use of the custom server side ad insertion, first you need an integration ID which will identify the provided sources and ads to the specific ad provider. | ||
|
||
### CustomSsaiDescriptionSerializer | ||
|
||
To play a source, inheriting the `CustomSsaiDescription` class is needed that will contain the necessary properties for the specific integration and be passed in the SourceDescription. | ||
Then, register a `CustomSsaiDescriptionSerializer` using the integration ID and provide a way to serialize/deserialize the new | ||
`CustomSsaiDescription`. | ||
|
||
Below is an example of a YoSpace integration showing `YospaceSsaiDescription` extending `CustomSsaiDescription`: | ||
|
||
```kotlin | ||
data class YospaceSsaiDescription constructor( | ||
/** | ||
* The type of the requested stream. | ||
* | ||
* Default: [YospaceStreamType.LIVE] | ||
*/ | ||
val streamType: YospaceStreamType = YospaceStreamType.LIVE, | ||
/** | ||
* Custom properties to set when initializing the Yospace session. | ||
*/ | ||
val sessionProperties: Session.SessionProperties = Session.SessionProperties() | ||
) : CustomSsaiDescription() { | ||
override val customIntegration = YospaceConnector.INTEGRATION_ID | ||
} | ||
``` | ||
|
||
And then, the implementation of the `CustomSsaiDescriptionSerializer` specific for YoSpace: | ||
|
||
```kotlin | ||
class YospaceSsaiDescriptionSerializer : CustomSsaiDescriptionSerializer { | ||
override fun fromJson(json: String): YospaceSsaiDescription { | ||
return Json.decodeFromString(json) | ||
} | ||
|
||
override fun toJson(value: CustomSsaiDescription): String { | ||
return Json.encodeToString(value) | ||
} | ||
} | ||
``` | ||
|
||
Finally, registering the `YospaceSsaiDescriptionSerializer`: | ||
|
||
```kotlin | ||
CustomSsaiDescriptionRegistry.register(YospaceConnector.INTEGRATION_ID, YospaceSsaiDescriptionSerializer()) | ||
``` | ||
|
||
### ServerSideAdIntegrationFactory | ||
|
||
You would also need to register a `ServerSideAdIntegrationFactory` that will receive a `ServerSideAdIntegrationController`. | ||
The controller can be used to create the THEOplayer `AdBreak`/`Ad` objects using the `AdBreakInit`/`AdInit` data. | ||
Additionally, it can be used to keep the player's state up-to-date such as when an ad begins or ends. | ||
|
||
The `ServerSideAdIntegrationFactory` requires an implementation of the `ServerSideAdIntegrationHandler` interface. | ||
The handler will provide few callbacks that can be overridden which allows you to setup and clear the integration as needed. | ||
|
||
#### Setting a Source | ||
|
||
When a new source is loaded into the player the `setSource(source: SourceDescription)` callback is triggered. | ||
It allows the integration to transform the source description, e.g. by calling an external service to replace the content URL (TypedSource.src), | ||
or by adding a fixed pre-roll linear ad to the list of ads (SourceDescription.ads). | ||
|
||
#### Skipping an Ad | ||
|
||
When an ad is requested to be skipped, the `skipAd(ad: Ad)` is called. | ||
At this point the controller should call its own `skipAd()` method. | ||
|
||
#### Resetting a Source | ||
|
||
Before a new source is loaded into the player, or before the player is destroyed, `resetSource()` is triggered. | ||
This allows the integration to clean up any source-specific resources, such as scheduled ads or pending HTTP requests. | ||
|
||
#### Destroying the player | ||
|
||
When the player is destroyed, the `destroy()` is called. | ||
This allows the integration to clean up any resources, such as UI views or event listeners. | ||
|
||
#### Creating Ad objects | ||
|
||
When the advertisement provider reports an ad, an `AdBreak` and an `Ad` object should be created using | ||
`createAdBreak(props: AdBreakInit)` and `createAd(props: AdInit, adBreak: AdBreak?)` methods respectively from the controller. | ||
For example, for a preroll `AdBreak` containing 2 advertisements it would be: | ||
|
||
```kotlin | ||
val adBreak = controller.createAdBreak(AdBreakInit(timeOffset = 0)) | ||
|
||
val firstAdInit = AdInit( | ||
type = "linear", | ||
skipOffset = 5, | ||
id = "first_ad_id", | ||
duration = 10, | ||
clickThrough = first_ad_click_through_url, | ||
resourceURI = first_ad_resource_url | ||
) | ||
val firstAd = controller.createAd(firstAdInit, adBreak) | ||
|
||
val secondAdInit = AdInit( | ||
type = "linear", | ||
skipOffset = 5, | ||
id = "second_ad_id", | ||
duration = 10, | ||
clickThrough = second_ad_click_through_url, | ||
resourceURI = second_ad_resource_url | ||
) | ||
val secondAd = controller.createAd(secondAdInit, adBreak) | ||
``` | ||
|
||
#### Playing an Ad | ||
|
||
When an Ad begins the playback, the controller must inform the player by calling `beginAd(ad: Ad)`, this will trigger the relevant AdBreak and Ad events. | ||
|
||
Additionally, during the playback of the Ad, calling `updateAdProgress(ad: Ad, progress: Double)` is needed to keep the player in sync with the progress. | ||
|
||
Finally, when the playback of the Ad is completed, `endAd(ad: Ad)` should be called to notify about it. |