ExoPlayer può essere utilizzato sia per l'inserimento di annunci lato client sia per l'inserimento di annunci lato server.
Inserimento di annunci lato client
Nell'inserimento di annunci lato client, il player passa dal caricamento di contenuti multimediali a diversi URL durante la transizione tra la riproduzione dei contenuti e gli annunci. Le informazioni sugli annunci vengono caricate separatamente dai contenuti multimediali, ad esempio da un tag annuncio XML VAST o VMAP. Queste possono includere le posizioni degli annunci relativi all'inizio dei contenuti, gli URI dei media degli annunci effettivi e i metadati, ad esempio se un determinato annuncio è ignorabile.
Quando utilizzi AdsMediaSource
di ExoPlayer per l'inserimento di annunci lato client, il player possiede le informazioni sugli annunci da riprodurre. Questo approccio presenta diversi vantaggi:
- Il player può esporre metadati e funzionalità relativi agli annunci utilizzando la propria API.
- I componenti dell'interfaccia utente di ExoPlayer possono mostrare automaticamente gli indicatori delle posizioni degli annunci e modificarne il comportamento a seconda che l'annuncio venga riprodotto o meno.
- All'interno, il player può mantenere un buffer costante durante le transizioni tra annunci e contenuti.
In questa configurazione, il player si occupa di passare da annunci a contenuti e viceversa, il che significa che le app non devono occuparsi di controllare più player in primo piano/sfondo separati per annunci e contenuti.
Quando si preparano i video dei contenuti e i tag annuncio da utilizzare con l'inserimento di annunci lato client, gli annunci dovrebbero essere posizionati in corrispondenza dei campioni di sincronizzazione (frame chiave) nel video di contenuti, in modo che il player possa riprendere la riproduzione dei contenuti senza problemi.
Supporto degli annunci dichiarativi
È possibile specificare un URI del tag annuncio durante la creazione di un MediaItem
:
Kotlin
val mediaItem = MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build()
Java
MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build();
Per attivare il supporto del player per gli elementi multimediali che specificano i tag annuncio, è necessario creare e iniettare un DefaultMediaSourceFactory
configurato con un AdsLoader.Provider
e un AdViewProvider
durante la creazione del player:
Kotlin
val mediaSourceFactory: MediaSource.Factory = DefaultMediaSourceFactory(context).setLocalAdInsertionComponents(adsLoaderProvider, playerView) val player = ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build()
Java
MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context) .setLocalAdInsertionComponents(adsLoaderProvider, /* adViewProvider= */ playerView); ExoPlayer player = new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
Internamente, DefaultMediaSourceFactory
inserirà l'origine media dei contenuti in un
AdsMediaSource
. AdsMediaSource
otterrà un AdsLoader
da AdsLoader.Provider
e lo utilizzerà per inserire gli annunci come definito dal tag annuncio dell'elemento multimediale.
PlayerView
di ExoPlayer implementa AdViewProvider
. La libreria IMA di ExoPlayer fornisce un AdsLoader
facile da usare, come descritto di seguito.
Playlist con annunci
Quando riproduci una playlist con più elementi multimediali, il comportamento predefinito prevede di richiedere il tag annuncio e memorizzare lo stato di riproduzione dell'annuncio una volta per ogni combinazione di ID media, URI contenuto e URI del tag annuncio. Ciò significa che gli utenti vedranno gli annunci per ogni elemento multimediale con annunci che hanno un ID media o un URI dei contenuti distinto, anche se gli URI dei tag annuncio corrispondono. Se un elemento multimediale viene ripetuto, l'utente vedrà gli annunci corrispondenti solo una volta (lo stato di riproduzione dell'annuncio indica se gli annunci sono stati riprodotti, quindi verranno ignorati dopo la prima occorrenza).
È possibile personalizzare questo comportamento passando un identificatore di annunci opaco con cui è collegato lo stato di riproduzione dell'annuncio per un determinato elemento multimediale, in base all'uguaglianza degli oggetti. Ecco un esempio in cui lo stato di riproduzione dell'annuncio è collegato solo all'URI del tag annuncio, anziché alla combinazione dell'ID media e dell'URI del tag annuncio, passando l'URI del tag annuncio come identificatore degli annunci. Il risultato è che gli annunci vengono caricati solo una volta e l'utente non visualizza annunci sul secondo elemento quando riproduce la playlist dall'inizio alla fine.
Kotlin
// Build the media items, passing the same ads identifier for both items, // which means they share ad playback state so ads play only once. val firstItem = MediaItem.Builder() .setUri(firstVideoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build() val secondItem = MediaItem.Builder() .setUri(secondVideoUri) .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build() player.addMediaItem(firstItem) player.addMediaItem(secondItem)
Java
// Build the media items, passing the same ads identifier for both items, // which means they share ad playback state so ads play only once. MediaItem firstItem = new MediaItem.Builder() .setUri(firstVideoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build(); MediaItem secondItem = new MediaItem.Builder() .setUri(secondVideoUri) .setAdsConfiguration( new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build()) .build(); player.addMediaItem(firstItem); player.addMediaItem(secondItem);
Libreria ExoPlayer IMA
La libreria IMA di ExoPlayer fornisce ImaAdsLoader
, semplificando l'integrazione dell'inserimento di annunci lato client nella tua app. Wrapping della funzionalità dell'SDK IMA lato client per supportare l'inserimento di annunci VAST/VMAP. Per istruzioni su come utilizzare la libreria, inclusa la gestione della riproduzione in background e della ripresa della riproduzione, consulta il file README.
L'applicazione di demo utilizza la libreria IMA e include diversi tag annuncio VAST/VMAP di esempio nell'elenco di esempi.
Considerazioni relative all'interfaccia utente
PlayerView
nasconde i controlli di trasporto durante la riproduzione degli annunci per impostazione predefinita, ma le app possono attivare/disattivare questo comportamento chiamando setControllerHideDuringAds
. L'SDK IMA mostra visualizzazioni aggiuntive nella parte superiore
del player durante la riproduzione di un annuncio (ad esempio, un link "Scopri di più" e un pulsante Salta,
se applicabile).
L'SDK IMA può segnalare se gli annunci sono coperti dalle visualizzazioni fornite dall'applicazione visualizzate sopra il player. Le app che devono sovrapporre visualizzazioni essenziali per il controllo della riproduzione devono registrarle con l'SDK IMA in modo che possano essere omesse dai calcoli della visibilità. Quando utilizzi PlayerView
come AdViewProvider
, vengono registrati automaticamente i relativi overlay di controllo. Le app
che utilizzano un'interfaccia utente del player personalizzata devono registrare le visualizzazioni in overlay restituendole da
AdViewProvider.getAdOverlayInfos
.
Per ulteriori informazioni sulle visualizzazioni overlay, consulta Open Measurement nell'SDK IMA.
Annunci companion
Alcuni tag annuncio contengono annunci companion aggiuntivi che possono essere mostrati negli "slot" dell'interfaccia utente di un'app. Questi slot possono essere trasmessi tramite
ImaAdsLoader.Builder.setCompanionAdSlots(slots)
. Per ulteriori informazioni, consulta
Aggiungere annunci di tipo companion.
Annunci autonomi
L'SDK IMA è progettato per inserire annunci nei contenuti multimediali, non per riprodurre annunci autonomi. Di conseguenza, la riproduzione di annunci autonomi non è supportata dalla libreria IMA. Per questo caso d'uso, ti consigliamo di utilizzare l'SDK Google Mobile Ads.
Utilizzare un SDK pubblicitario di terze parti
Se devi caricare annunci tramite un SDK per gli annunci di terze parti, vale la pena verificare se
fornisce già un'integrazione ExoPlayer. In caso contrario, l'approccio consigliato è implementare un
AdsLoader
personalizzato che ingloba l'SDK per gli annunci di terze parti,
poiché offre i vantaggi di AdsMediaSource
descritti sopra.
ImaAdsLoader
funge da implementazione di esempio.
In alternativa, puoi utilizzare il supporto delle playlist di ExoPlayer per creare una sequenza di annunci e clip di contenuti:
Kotlin
// A pre-roll ad. val preRollAd = MediaItem.fromUri(preRollAdUri) // The start of the content. val contentStart = MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration(ClippingConfiguration.Builder().setEndPositionMs(120000).build()) .build() // A mid-roll ad. val midRollAd = MediaItem.fromUri(midRollAdUri) // The rest of the content val contentEnd = MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration(ClippingConfiguration.Builder().setStartPositionMs(120000).build()) .build() // Build the playlist. player.addMediaItem(preRollAd) player.addMediaItem(contentStart) player.addMediaItem(midRollAd) player.addMediaItem(contentEnd)
Java
// A pre-roll ad. MediaItem preRollAd = MediaItem.fromUri(preRollAdUri); // The start of the content. MediaItem contentStart = new MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration( new ClippingConfiguration.Builder().setEndPositionMs(120_000).build()) .build(); // A mid-roll ad. MediaItem midRollAd = MediaItem.fromUri(midRollAdUri); // The rest of the content MediaItem contentEnd = new MediaItem.Builder() .setUri(contentUri) .setClippingConfiguration( new ClippingConfiguration.Builder().setStartPositionMs(120_000).build()) .build(); // Build the playlist. player.addMediaItem(preRollAd); player.addMediaItem(contentStart); player.addMediaItem(midRollAd); player.addMediaItem(contentEnd);
Inserimento di annunci lato server
Nell'inserimento di annunci lato server (chiamato anche inserimento di annunci dinamici o DAI), lo stream multimediale contiene sia annunci sia contenuti. Un manifest DASH può fare riferimento sia ai contenuti sia ai segmenti di annunci, eventualmente in periodi distinti. Per HLS, consulta la documentazione di Apple sulla incorporazione di annunci in una playlist.
Quando si utilizza l'inserimento di annunci lato server, il client potrebbe dover risolvere dinamicamente l'URL media per ottenere lo stream cucito, potrebbe dover mostrare overlay degli annunci nell'interfaccia utente o potrebbe dover segnalare eventi a un SDK o ad server pubblicitari.
DefaultMediaSourceFactory
di ExoPlayer può delegare tutte queste attività a un'MediaSource
di inserzione di annunci lato server per gli URI che utilizzano lo schema ssai://
:
Kotlin
val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setServerSideAdInsertionMediaSourceFactory(ssaiFactory) ) .build()
Java
Player player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context) .setServerSideAdInsertionMediaSourceFactory(ssaiFactory)) .build();
Libreria ExoPlayer IMA
La libreria IMA di ExoPlayer fornisce ImaServerSideAdInsertionMediaSource
,
semplificando l'integrazione con gli stream di annunci inseriti lato server di IMA nella
app. Racchiude la funzionalità dell'SDK IMA DAI per Android e integra completamente
i metadati degli annunci forniti nel player. Ad esempio, ti consente di utilizzare metodi come Player.isPlayingAd()
, ascoltare le transizioni tra contenuti e annunci e lasciare che sia il player a gestire la logica di riproduzione degli annunci, ad esempio ignorare gli annunci già riprodotti.
Per utilizzare questo corso, devi configurare
ImaServerSideAdInsertionMediaSource.AdsLoader
e
ImaServerSideAdInsertionMediaSource.Factory
e collegarli al player:
Kotlin
// MediaSource.Factory to load the actual media stream. val defaultMediaSourceFactory = DefaultMediaSourceFactory(context) // AdsLoader that can be reused for multiple playbacks. val adsLoader = ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build() // MediaSource.Factory to create the ad sources for the current player. val adsMediaSourceFactory = ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory) // Configure DefaultMediaSourceFactory to create both IMA DAI sources and // regular media sources. If you just play IMA DAI streams, you can also use // adsMediaSourceFactory directly. defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory) // Set the MediaSource.Factory on the Player. val player = ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build() // Set the player on the AdsLoader adsLoader.setPlayer(player)
Java
// MediaSource.Factory to load the actual media stream. DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory(context); // AdsLoader that can be reused for multiple playbacks. ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader = new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build(); // MediaSource.Factory to create the ad sources for the current player. ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory = new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory); // Configure DefaultMediaSourceFactory to create both IMA DAI sources and // regular media sources. If you just play IMA DAI streams, you can also use // adsMediaSourceFactory directly. defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory); // Set the MediaSource.Factory on the Player. Player player = new ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build(); // Set the player on the AdsLoader adsLoader.setPlayer(player);
Carica la chiave asset IMA o l'ID origine di contenuto e l'ID video creando un URL
con ImaServerSideAdInsertionUriBuilder
:
Kotlin
val ssaiUri = ImaServerSideAdInsertionUriBuilder() .setAssetKey(assetKey) .setFormat(C.CONTENT_TYPE_HLS) .build() player.setMediaItem(MediaItem.fromUri(ssaiUri))
Java
Uri ssaiUri = new ImaServerSideAdInsertionUriBuilder() .setAssetKey(assetKey) .setFormat(C.CONTENT_TYPE_HLS) .build(); player.setMediaItem(MediaItem.fromUri(ssaiUri));
Infine, rilascia il caricatore degli annunci quando non è più utilizzato:
Kotlin
adsLoader.release()
Java
adsLoader.release();
Considerazioni relative all'interfaccia utente
Anche per l'inserimento di annunci lato server valgono le stesse considerazioni sull'interfaccia utente valide per l'inserimento di annunci lato client.
Annunci companion
Alcuni tag annuncio contengono annunci companion aggiuntivi che possono essere mostrati in "slot" nell'interfaccia utente di un'app. Questi slot possono essere trasmessi tramite
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots)
.
Per ulteriori informazioni, consulta Aggiungere annunci di tipo companion.
Utilizzo di un SDK pubblicitario di terze parti
Se devi caricare gli annunci utilizzando un SDK annunci di terze parti, vale la pena verificare se offre già un'integrazione di ExoPlayer. In caso contrario, ti consigliamo di fornire un MediaSource
personalizzato che accetti gli URI con lo schema ssai://
simile a ImaServerSideAdInsertionMediaSource
.
La logica effettiva della creazione della struttura dell'annuncio può essere delegata all'elemento di scopo generale ServerSideAdInsertionMediaSource
, che racchiude uno stream MediaSource
e consente all'utente di impostare e aggiornare il AdPlaybackState
che rappresenta i metadati dell'annuncio.
Spesso, gli stream di annunci inseriti lato server contengono eventi a tempo per notificare al player i metadati degli annunci. Consulta la sezione Formati supportati per informazioni sui formati dei metadati a tempo supportati da ExoPlayer. Le implementazioni dell'SDK per gli annunci personalizzati MediaSource
possono ascoltare gli eventi dei metadati con temporizzazione del player utilizzando
Player.Listener.onMetadata
.