1*30877f79SAndroid Build Coastguard Worker---
2*30877f79SAndroid Build Coastguard Workertitle: Ad insertion
3*30877f79SAndroid Build Coastguard Worker---
4*30877f79SAndroid Build Coastguard Worker
5*30877f79SAndroid Build Coastguard WorkerExoPlayer can be used for both client-side and server-side ad insertion.
6*30877f79SAndroid Build Coastguard Worker
7*30877f79SAndroid Build Coastguard Worker## Client-side ad insertion ##
8*30877f79SAndroid Build Coastguard Worker
9*30877f79SAndroid Build Coastguard WorkerIn client-side ad insertion, the player switches between loading media from
10*30877f79SAndroid Build Coastguard Workerdifferent URLs as it transitions between playing content and ads. Information
11*30877f79SAndroid Build Coastguard Workerabout ads is loaded separately from the media, such as from an XML [VAST][] or
12*30877f79SAndroid Build Coastguard Worker[VMAP][] ad tag. This can include ad cue positions relative to the start of the
13*30877f79SAndroid Build Coastguard Workercontent, the actual ad media URIs and metadata such as whether a given ad is
14*30877f79SAndroid Build Coastguard Workerskippable.
15*30877f79SAndroid Build Coastguard Worker
16*30877f79SAndroid Build Coastguard WorkerWhen using ExoPlayer's `AdsMediaSource` for client-side ad insertion, the player
17*30877f79SAndroid Build Coastguard Workerhas information about the ads to be played. This has several benefits:
18*30877f79SAndroid Build Coastguard Worker
19*30877f79SAndroid Build Coastguard Worker* The player can expose metadata and functionality relating to ads via its API.
20*30877f79SAndroid Build Coastguard Worker* [ExoPlayer UI components][] can show markers for ad positions automatically,
21*30877f79SAndroid Build Coastguard Worker  and change their behavior depending on whether ad is playing.
22*30877f79SAndroid Build Coastguard Worker* Internally, the player can keep a consistent buffer across transitions between
23*30877f79SAndroid Build Coastguard Worker  ads and content.
24*30877f79SAndroid Build Coastguard Worker
25*30877f79SAndroid Build Coastguard WorkerIn this setup, the player takes care of switching between ads and content, which
26*30877f79SAndroid Build Coastguard Workermeans that apps don't need to take care of controlling multiple separate
27*30877f79SAndroid Build Coastguard Workerbackground/foreground players for ads and content.
28*30877f79SAndroid Build Coastguard Worker
29*30877f79SAndroid Build Coastguard WorkerWhen preparing content videos and ad tags for use with client-side ad insertion,
30*30877f79SAndroid Build Coastguard Workerads should ideally be positioned at synchronization samples (keyframes) in the
31*30877f79SAndroid Build Coastguard Workercontent video so that the player can resume content playback seamlessly.
32*30877f79SAndroid Build Coastguard Worker
33*30877f79SAndroid Build Coastguard Worker### Declarative ad support ###
34*30877f79SAndroid Build Coastguard Worker
35*30877f79SAndroid Build Coastguard WorkerAn ad tag URI can be specified when building a `MediaItem`:
36*30877f79SAndroid Build Coastguard Worker
37*30877f79SAndroid Build Coastguard Worker~~~
38*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem =
39*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
40*30877f79SAndroid Build Coastguard Worker        .setUri(videoUri)
41*30877f79SAndroid Build Coastguard Worker        .setAdsConfiguration(
42*30877f79SAndroid Build Coastguard Worker            new MediaItem.AdsConfiguration.Builder(adTagUri).build())
43*30877f79SAndroid Build Coastguard Worker        .build();
44*30877f79SAndroid Build Coastguard Worker~~~
45*30877f79SAndroid Build Coastguard Worker{: .language-java}
46*30877f79SAndroid Build Coastguard Worker
47*30877f79SAndroid Build Coastguard WorkerTo enable player support for media items that specify ad tags, it's necessary to
48*30877f79SAndroid Build Coastguard Workerbuild and inject a `DefaultMediaSourceFactory` configured with an
49*30877f79SAndroid Build Coastguard Worker`AdsLoader.Provider` and an `AdViewProvider` when creating the player:
50*30877f79SAndroid Build Coastguard Worker
51*30877f79SAndroid Build Coastguard Worker~~~
52*30877f79SAndroid Build Coastguard WorkerMediaSource.Factory mediaSourceFactory =
53*30877f79SAndroid Build Coastguard Worker    new DefaultMediaSourceFactory(context)
54*30877f79SAndroid Build Coastguard Worker        .setAdsLoaderProvider(adsLoaderProvider)
55*30877f79SAndroid Build Coastguard Worker        .setAdViewProvider(playerView);
56*30877f79SAndroid Build Coastguard WorkerExoPlayer player = new ExoPlayer.Builder(context)
57*30877f79SAndroid Build Coastguard Worker    .setMediaSourceFactory(mediaSourceFactory)
58*30877f79SAndroid Build Coastguard Worker    .build();
59*30877f79SAndroid Build Coastguard Worker~~~
60*30877f79SAndroid Build Coastguard Worker{: .language-java}
61*30877f79SAndroid Build Coastguard Worker
62*30877f79SAndroid Build Coastguard WorkerInternally, `DefaultMediaSourceFactory` will wrap the content media source in an
63*30877f79SAndroid Build Coastguard Worker`AdsMediaSource`. The `AdsMediaSource` will obtain an `AdsLoader` from the
64*30877f79SAndroid Build Coastguard Worker`AdsLoader.Provider` and use it to insert ads as defined by the media item's ad
65*30877f79SAndroid Build Coastguard Workertag.
66*30877f79SAndroid Build Coastguard Worker
67*30877f79SAndroid Build Coastguard WorkerExoPlayer's `StyledPlayerView` and `PlayerView` UI components both
68*30877f79SAndroid Build Coastguard Workerimplement `AdViewProvider`. The IMA extension provides an easy to use
69*30877f79SAndroid Build Coastguard Worker`AdsLoader`, as described below.
70*30877f79SAndroid Build Coastguard Worker
71*30877f79SAndroid Build Coastguard Worker### Playlists with ads ###
72*30877f79SAndroid Build Coastguard Worker
73*30877f79SAndroid Build Coastguard WorkerWhen playing a [playlist][] with multiple media items, the default behavior is
74*30877f79SAndroid Build Coastguard Workerto request the ad tag and store ad playback state once for each media ID,
75*30877f79SAndroid Build Coastguard Workercontent URI and ad tag URI combination. This means that users will see ads for
76*30877f79SAndroid Build Coastguard Workerevery media item with ads that has a distinct media ID or content URI, even if
77*30877f79SAndroid Build Coastguard Workerthe ad tag URIs match. If a media item is repeated, the user will see the
78*30877f79SAndroid Build Coastguard Workercorresponding ads only once (the ad playback state stores whether ads have been
79*30877f79SAndroid Build Coastguard Workerplayed, so they are skipped after their first occurrence).
80*30877f79SAndroid Build Coastguard Worker
81*30877f79SAndroid Build Coastguard WorkerIt's possible to customize this behavior by passing an opaque ads identifier
82*30877f79SAndroid Build Coastguard Workerwith which ad playback state for a given media item is linked, based on object
83*30877f79SAndroid Build Coastguard Workerequality. Here is an example where ad playback state is linked to the ad tag
84*30877f79SAndroid Build Coastguard WorkerURI only, rather than the combination of the media ID and ad tag URI, by
85*30877f79SAndroid Build Coastguard Workerpassing the ad tag URI as the ads identifier. The effect is that ads will load
86*30877f79SAndroid Build Coastguard Workeronly once and the user will not see ads on the second item when playing the
87*30877f79SAndroid Build Coastguard Workerplaylist from start to finish.
88*30877f79SAndroid Build Coastguard Worker
89*30877f79SAndroid Build Coastguard Worker~~~
90*30877f79SAndroid Build Coastguard Worker// Build the media items, passing the same ads identifier for both items,
91*30877f79SAndroid Build Coastguard Worker// which means they share ad playback state so ads play only once.
92*30877f79SAndroid Build Coastguard WorkerMediaItem firstItem =
93*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
94*30877f79SAndroid Build Coastguard Worker        .setUri(firstVideoUri)
95*30877f79SAndroid Build Coastguard Worker        .setAdsConfiguration(
96*30877f79SAndroid Build Coastguard Worker            new MediaItem.AdsConfiguration.Builder(adTagUri)
97*30877f79SAndroid Build Coastguard Worker                .setAdsId(adTagUri)
98*30877f79SAndroid Build Coastguard Worker                .build())
99*30877f79SAndroid Build Coastguard Worker        .build();
100*30877f79SAndroid Build Coastguard WorkerMediaItem secondItem =
101*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
102*30877f79SAndroid Build Coastguard Worker        .setUri(secondVideoUri)
103*30877f79SAndroid Build Coastguard Worker        .setAdsConfiguration(
104*30877f79SAndroid Build Coastguard Worker            new MediaItem.AdsConfiguration.Builder(adTagUri)
105*30877f79SAndroid Build Coastguard Worker                .setAdsId(adTagUri)
106*30877f79SAndroid Build Coastguard Worker                .build())
107*30877f79SAndroid Build Coastguard Worker        .build();
108*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(firstItem);
109*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(secondItem);
110*30877f79SAndroid Build Coastguard Worker~~~
111*30877f79SAndroid Build Coastguard Worker{: .language-java}
112*30877f79SAndroid Build Coastguard Worker
113*30877f79SAndroid Build Coastguard Worker### IMA extension ###
114*30877f79SAndroid Build Coastguard Worker
115*30877f79SAndroid Build Coastguard WorkerThe [ExoPlayer IMA extension][] provides `ImaAdsLoader`, making it easy to
116*30877f79SAndroid Build Coastguard Workerintegrate client-side ad insertion into your app. It wraps the functionality of
117*30877f79SAndroid Build Coastguard Workerthe [client-side IMA SDK][] to support insertion of VAST/VMAP ads. For
118*30877f79SAndroid Build Coastguard Workerinstructions on how to use the extension, including how to handle backgrounding
119*30877f79SAndroid Build Coastguard Workerand resuming playback, please see the [README][].
120*30877f79SAndroid Build Coastguard Worker
121*30877f79SAndroid Build Coastguard WorkerThe [demo application][] uses the IMA extension, and includes several sample
122*30877f79SAndroid Build Coastguard WorkerVAST/VMAP ad tags in the sample list.
123*30877f79SAndroid Build Coastguard Worker
124*30877f79SAndroid Build Coastguard Worker#### UI considerations ####
125*30877f79SAndroid Build Coastguard Worker
126*30877f79SAndroid Build Coastguard Worker`StyledPlayerView` and `PlayerView` hide controls during playback of ads
127*30877f79SAndroid Build Coastguard Workerby default, but apps can toggle this behavior by calling
128*30877f79SAndroid Build Coastguard Worker`setControllerHideDuringAds`, which is defined on both views. The IMA SDK will
129*30877f79SAndroid Build Coastguard Workershow additional views on top of the player while an ad is playing (e.g., a 'more
130*30877f79SAndroid Build Coastguard Workerinfo' link and a skip button, if applicable).
131*30877f79SAndroid Build Coastguard Worker
132*30877f79SAndroid Build Coastguard WorkerSince advertisers expect a consistent experience across apps, the IMA SDK does
133*30877f79SAndroid Build Coastguard Workernot allow customization of the views that it shows while an ad is playing. It is
134*30877f79SAndroid Build Coastguard Workertherefore not possible to remove or reposition the skip button, change the
135*30877f79SAndroid Build Coastguard Workerfonts, or make other customizations to the visual appearance of these views.
136*30877f79SAndroid Build Coastguard Worker{:.info}
137*30877f79SAndroid Build Coastguard Worker
138*30877f79SAndroid Build Coastguard WorkerThe IMA SDK may report whether ads are obscured by application provided views
139*30877f79SAndroid Build Coastguard Workerrendered on top of the player. Apps that need to overlay views that are
140*30877f79SAndroid Build Coastguard Workeressential for controlling playback must register them with the IMA SDK so that
141*30877f79SAndroid Build Coastguard Workerthey can be omitted from viewability calculations. When using `StyledPlayerView`
142*30877f79SAndroid Build Coastguard Workeror `PlayerView` as the `AdViewProvider`, they will automatically register
143*30877f79SAndroid Build Coastguard Workertheir control overlays. Apps that use a custom player UI must register overlay
144*30877f79SAndroid Build Coastguard Workerviews by returning them from `AdViewProvider.getAdOverlayInfos`.
145*30877f79SAndroid Build Coastguard Worker
146*30877f79SAndroid Build Coastguard WorkerFor more information about overlay views, see
147*30877f79SAndroid Build Coastguard Worker[Open Measurement in the IMA SDK][].
148*30877f79SAndroid Build Coastguard Worker
149*30877f79SAndroid Build Coastguard Worker#### Companion ads ####
150*30877f79SAndroid Build Coastguard Worker
151*30877f79SAndroid Build Coastguard WorkerSome ad tags contain additional companion ads that can be shown in 'slots' in an
152*30877f79SAndroid Build Coastguard Workerapp UI. These slots can be passed via
153*30877f79SAndroid Build Coastguard Worker`ImaAdsLoader.Builder.setCompanionAdSlots(slots)`. For more information see
154*30877f79SAndroid Build Coastguard Worker[Adding Companion Ads][].
155*30877f79SAndroid Build Coastguard Worker
156*30877f79SAndroid Build Coastguard Worker#### Standalone ads ####
157*30877f79SAndroid Build Coastguard Worker
158*30877f79SAndroid Build Coastguard WorkerThe IMA SDK is designed for inserting ads into media content, not for playing
159*30877f79SAndroid Build Coastguard Workerstandalone ads by themselves. Hence playback of standalone ads is not supported
160*30877f79SAndroid Build Coastguard Workerby the IMA extension. We recommend using the [Google Mobile Ads SDK][] instead
161*30877f79SAndroid Build Coastguard Workerfor this use case.
162*30877f79SAndroid Build Coastguard Worker
163*30877f79SAndroid Build Coastguard Worker### Using a third-party ads SDK ###
164*30877f79SAndroid Build Coastguard Worker
165*30877f79SAndroid Build Coastguard WorkerIf you need to load ads via a third-party ads SDK, it's worth checking whether
166*30877f79SAndroid Build Coastguard Workerit already provides an ExoPlayer integration. If not, implementing a custom
167*30877f79SAndroid Build Coastguard Worker`AdsLoader` that wraps the third-party ads SDK is the recommended approach,
168*30877f79SAndroid Build Coastguard Workersince it provides the benefits of `AdsMediaSource` described above.
169*30877f79SAndroid Build Coastguard Worker`ImaAdsLoader` acts as an example implementation.
170*30877f79SAndroid Build Coastguard Worker
171*30877f79SAndroid Build Coastguard WorkerAlternatively, you can use ExoPlayer's [playlist support][] to build a sequence
172*30877f79SAndroid Build Coastguard Workerof ads and content clips:
173*30877f79SAndroid Build Coastguard Worker
174*30877f79SAndroid Build Coastguard Worker~~~
175*30877f79SAndroid Build Coastguard Worker// A pre-roll ad.
176*30877f79SAndroid Build Coastguard WorkerMediaItem preRollAd = MediaItem.fromUri(preRollAdUri);
177*30877f79SAndroid Build Coastguard Worker// The start of the content.
178*30877f79SAndroid Build Coastguard WorkerMediaItem contentStart =
179*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
180*30877f79SAndroid Build Coastguard Worker        .setUri(contentUri)
181*30877f79SAndroid Build Coastguard Worker        .setClippingConfiguration(
182*30877f79SAndroid Build Coastguard Worker            new ClippingConfiguration.Builder()
183*30877f79SAndroid Build Coastguard Worker                .setEndPositionMs(120_000)
184*30877f79SAndroid Build Coastguard Worker                .build())
185*30877f79SAndroid Build Coastguard Worker        .build();
186*30877f79SAndroid Build Coastguard Worker// A mid-roll ad.
187*30877f79SAndroid Build Coastguard WorkerMediaItem midRollAd = MediaItem.fromUri(midRollAdUri);
188*30877f79SAndroid Build Coastguard Worker// The rest of the content
189*30877f79SAndroid Build Coastguard WorkerMediaItem contentEnd =
190*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
191*30877f79SAndroid Build Coastguard Worker        .setUri(contentUri)
192*30877f79SAndroid Build Coastguard Worker        .setClippingConfiguration(
193*30877f79SAndroid Build Coastguard Worker            new ClippingConfiguration.Builder()
194*30877f79SAndroid Build Coastguard Worker                .setStartPositionMs(120_000)
195*30877f79SAndroid Build Coastguard Worker                .build())
196*30877f79SAndroid Build Coastguard Worker        .build();
197*30877f79SAndroid Build Coastguard Worker
198*30877f79SAndroid Build Coastguard Worker// Build the playlist.
199*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(preRollAd);
200*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(contentStart);
201*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(midRollAd);
202*30877f79SAndroid Build Coastguard Workerplayer.addMediaItem(contentEnd);
203*30877f79SAndroid Build Coastguard Worker~~~
204*30877f79SAndroid Build Coastguard Worker{: .language-java}
205*30877f79SAndroid Build Coastguard Worker
206*30877f79SAndroid Build Coastguard Worker## Server-side ad insertion ##
207*30877f79SAndroid Build Coastguard Worker
208*30877f79SAndroid Build Coastguard WorkerIn server-side ad insertion (also called dynamic ad insertion, or DAI), the
209*30877f79SAndroid Build Coastguard Workermedia stream contains both ads and content. A DASH manifest may point to both
210*30877f79SAndroid Build Coastguard Workercontent and ad segments, possibly in separate periods. For HLS, see the Apple
211*30877f79SAndroid Build Coastguard Workerdocumentation on [incorporating ads into a playlist][].
212*30877f79SAndroid Build Coastguard Worker
213*30877f79SAndroid Build Coastguard WorkerWhen using server-side ad insertion the client may need to report tracking
214*30877f79SAndroid Build Coastguard Workerevents to an ad SDK or ad server. For example, the media stream may include
215*30877f79SAndroid Build Coastguard Workertimed events that need to be reported by the client (see [supported formats][]
216*30877f79SAndroid Build Coastguard Workerfor information on what timed metadata formats are supported by ExoPlayer). Apps
217*30877f79SAndroid Build Coastguard Workercan listen for timed metadata events from the player, e.g., via
218*30877f79SAndroid Build Coastguard Worker`ExoPlayer.addMetadataOutput`.
219*30877f79SAndroid Build Coastguard Worker
220*30877f79SAndroid Build Coastguard WorkerThe IMA extension currently only handles client-side ad insertion. It does not
221*30877f79SAndroid Build Coastguard Workerprovide any integration with the DAI part of the IMA SDK.
222*30877f79SAndroid Build Coastguard Worker{:.info}
223*30877f79SAndroid Build Coastguard Worker
224*30877f79SAndroid Build Coastguard Worker[VAST]: https://www.iab.com/wp-content/uploads/2015/06/VASTv3_0.pdf
225*30877f79SAndroid Build Coastguard Worker[VMAP]: https://www.iab.com/guidelines/digital-video-multiple-ad-playlist-vmap-1-0-1/
226*30877f79SAndroid Build Coastguard Worker[ExoPlayer UI components]: {{ site.baseurl }}/ui-components.html
227*30877f79SAndroid Build Coastguard Worker[ExoPlayer IMA extension]: https://github.com/google/ExoPlayer/tree/release-v2/extensions/ima
228*30877f79SAndroid Build Coastguard Worker[client-side IMA SDK]: https://developers.google.com/interactive-media-ads/docs/sdks/android
229*30877f79SAndroid Build Coastguard Worker[README]: https://github.com/google/ExoPlayer/tree/release-v2/extensions/ima
230*30877f79SAndroid Build Coastguard Worker[demo application]: {{ site.baseurl }}/demo-application.html
231*30877f79SAndroid Build Coastguard Worker[Open Measurement in the IMA SDK]: https://developers.google.com/interactive-media-ads/docs/sdks/android/omsdk
232*30877f79SAndroid Build Coastguard Worker[Adding Companion Ads]: https://developers.google.com/interactive-media-ads/docs/sdks/android/companions
233*30877f79SAndroid Build Coastguard Worker[playlist]: {{ site.baseurl }}/playlists.html
234*30877f79SAndroid Build Coastguard Worker[playlist support]: {{ site.baseurl }}/playlists.html
235*30877f79SAndroid Build Coastguard Worker[incorporating ads into a playlist]: https://developer.apple.com/documentation/http_live_streaming/example_playlists_for_http_live_streaming/incorporating_ads_into_a_playlist
236*30877f79SAndroid Build Coastguard Worker[supported formats]: {{ site.baseurl }}/supported-formats.html
237*30877f79SAndroid Build Coastguard Worker[Google Mobile Ads SDK]: https://developers.google.com/admob/android/quick-start
238