ExoPlayer può essere utilizzato per l'inserimento di annunci lato client e lato server.
Inserimento di annunci lato client
Nell'inserimento di annunci lato client, il player passa dal caricamento dei contenuti multimediali da URL diversi durante la transizione tra la riproduzione di contenuti e 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 dei cue pubblicitari rispetto all'inizio dei contenuti, gli URI dei media pubblicitari 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
dispone di informazioni sugli annunci da riprodurre. Questo approccio offre diversi vantaggi:
- Il player può esporre metadati e funzionalità relativi agli annunci utilizzando la sua API.
- I componenti dell'interfaccia utente di ExoPlayer possono mostrare automaticamente i marcatori per le posizioni degli annunci e modificare il loro comportamento a seconda che l'annuncio sia in riproduzione.
- A livello interno, il player può mantenere un buffer coerente durante le transizioni tra annunci e contenuti.
In questa configurazione, il player si occupa di passare da un annuncio a un contenuto e viceversa, il che significa che le app non devono occuparsi di controllare più player separati in background/in primo piano per annunci e contenuti.
Quando prepari i video dei contenuti e i tag annuncio per l'utilizzo con l'inserimento di annunci lato client, gli annunci devono essere posizionati idealmente in corrispondenza dei campioni di sincronizzazione (fotogrammi chiave) nel video dei 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 inserire 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. Il AdsMediaSource otterrà un AdsLoader dal
AdsLoader.Provider e lo utilizzerà per inserire gli annunci come definito dal tag
annuncio dell'elemento multimediale.
PlayerView di ExoPlayer implementa AdViewProvider. La libreria ExoPlayer IMA
fornisce un AdsLoader facile da usare, come descritto di seguito.
Playlist con annunci
Quando riproduci una playlist con più elementi multimediali, il comportamento predefinito è richiedere il tag annuncio e memorizzare lo stato di riproduzione dell'annuncio una volta per ogni combinazione di ID elemento multimediale, URI dei contenuti e URI del tag annuncio. Ciò significa che gli utenti vedranno annunci per ogni elemento multimediale con annunci che hanno un ID multimediale 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 una sola volta (lo stato di riproduzione degli annunci memorizza se gli annunci sono stati riprodotti, quindi vengono ignorati dopo la prima occorrenza).
È possibile personalizzare questo comportamento passando un identificatore pubblicità opaco a cui è collegato lo stato di riproduzione degli annunci per un determinato elemento multimediale, in base all'uguaglianza dell'oggetto. Ecco un esempio in cui lo stato di riproduzione dell'annuncio è collegato solo all'URI del tag annuncio, anziché alla combinazione di ID media e URI del tag annuncio, passando l'URI del tag annuncio come identificatore degli annunci. Il risultato è che gli annunci verranno caricati una sola volta e l'utente non vedrà 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);
Inserimento di annunci lato client guidato dal server
ExoPlayer è dotato di HlsInterstitialsAdsLoader che supporta l'inserimento automatico lato client degli annunci definiti nella playlist HLS. Consulta
la sezione relativa a HlsInterstitialsAdsLoader nella pagina HLS.
Libreria IMA di ExoPlayer
La libreria ExoPlayer IMA fornisce ImaAdsLoader, semplificando l'integrazione dell'inserimento di annunci lato client nella tua app. Esegue il 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 dell'esecuzione in background
e la ripresa della riproduzione, consulta il file README.
L'applicazione demo utilizza la libreria IMA e include diversi tag annuncio VAST/VMAP di esempio nell'elenco di esempio.
Considerazioni relative alla UI
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
mostrerà ulteriori visualizzazioni sopra il 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 oscurati dalle visualizzazioni fornite dall'applicazione
visualizzate sopra il player. Le app che devono sovrapporre visualizzazioni essenziali per controllare la riproduzione devono registrarle con l'SDK IMA in modo che possano essere omesse dai calcoli della visibilità. Quando utilizzi PlayerView come
AdViewProvider, registra automaticamente le sovrapposizioni dei controlli. Le app
che utilizzano un'interfaccia utente del player personalizzata devono registrare le visualizzazioni overlay restituendole da
AdViewProvider.getAdOverlayInfos.
Per saperne di più sulle visualizzazioni overlay, consulta Open Measurement nell'SDK IMA.
Annunci companion
Alcuni tag annuncio contengono annunci companion aggiuntivi che possono essere mostrati negli "slot" di un'interfaccia utente dell'app. Questi slot possono essere passati tramite
ImaAdsLoader.Builder.setCompanionAdSlots(slots). Per saperne di più, consulta la sezione
Aggiungere annunci companion.
Annunci autonomi
L'SDK IMA è progettato per inserire annunci nei contenuti multimediali, non per riprodurre annunci autonomi. Pertanto, la riproduzione di annunci autonomi non è supportata dalla libreria IMA. Per questo caso d'uso, ti consigliamo di utilizzare l'SDK Google Mobile Ads.
Utilizzo di un SDK per gli annunci di terze parti
Se devi caricare gli annunci tramite un SDK per gli annunci di terze parti, ti consigliamo di verificare se
fornisce già un'integrazione di ExoPlayer. In caso contrario, l'approccio consigliato è l'implementazione di un AdsLoader personalizzato che esegue il wrapping dell'SDK per gli annunci di terze parti, poiché offre i vantaggi di AdsMediaSource descritti in precedenza.
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( MediaItem.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( MediaItem.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 MediaItem.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 MediaItem.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 che contenuti. Un manifest DASH può puntare sia a segmenti di contenuti che di annunci, possibilmente in periodi separati. Per HLS, consulta la documentazione di Apple sull'incorporamento di annunci in una playlist.
Quando si utilizza l'inserimento di annunci lato server, il client potrebbe dover risolvere l'URL dei contenuti multimediali in modo dinamico per ottenere lo stream unito, potrebbe dover visualizzare le overlay degli annunci nell'interfaccia utente o potrebbe dover segnalare gli eventi a un SDK per gli annunci o a un ad server.
DefaultMediaSourceFactory di ExoPlayer può delegare tutte queste attività a un'inserzione di annunci lato server MediaSource 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 IMA di ExoPlayer
La libreria ExoPlayer IMA fornisce ImaServerSideAdInsertionMediaSource,
semplificando l'integrazione con i flussi di annunci inseriti lato server di IMA nella tua
app. Esegue il wrapping della funzionalità dell'SDK IMA DAI per Android e integra completamente
i metadati degli annunci forniti nel player. Ad esempio, questo ti consente di utilizzare metodi come Player.isPlayingAd(), ascoltare le transizioni tra contenuti e annunci e lasciare che il player gestisca la logica di riproduzione degli annunci, ad esempio saltando 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 dell'asset IMA o l'ID origine contenuti 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 di annunci quando non viene più utilizzato:
Kotlin
adsLoader.release()
Java
adsLoader.release();
Considerazioni relative alla UI
Le stesse considerazioni sull'interfaccia utente per l'inserimento di annunci lato client si applicano anche all'inserimento di annunci lato server.
Annunci companion
Alcuni tag annuncio contengono annunci companion aggiuntivi che possono essere mostrati negli "slot" di un'interfaccia utente dell'app. Questi slot possono essere passati tramite
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots).
Per saperne di più, consulta Aggiungere annunci companion.
Utilizzo di un SDK per gli annunci di terze parti
Se devi caricare gli annunci utilizzando un SDK per gli annunci di terze parti, ti consigliamo di verificare se
fornisce già un'integrazione di ExoPlayer. In caso contrario, ti consigliamo di
fornire un MediaSource personalizzato che accetti URI con lo schema ssai://
simile a ImaServerSideAdInsertionMediaSource.
La logica effettiva di creazione della struttura dell'annuncio può essere delegata a ServerSideAdInsertionMediaSource di uso generale, che racchiude uno stream MediaSource e consente all'utente di impostare e aggiornare AdPlaybackState che rappresenta i metadati dell'annuncio.
Spesso, i flussi di annunci inseriti lato server contengono eventi temporizzati per notificare al player
i metadati degli annunci. Per informazioni sui formati dei metadati temporizzati supportati da ExoPlayer, consulta la sezione Formati supportati. Le implementazioni dell'SDK per gli annunci personalizzati MediaSource
possono rilevare gli eventi di metadati temporizzati dal lettore utilizzando
Player.Listener.onMetadata.