Inserimento degli annunci

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 da URL diversi durante il passaggio dalla riproduzione di contenuti agli 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 informazioni sugli annunci da riprodurre. Questo approccio presenta numerosi 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 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 a occuparsi del passaggio 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 prepari i video dei contenuti e i tag annuncio per l'utilizzo con l'inserimento di annunci lato client, idealmente gli annunci devono essere posizionati nei sample di sincronizzazione (keyframe) nel video dei contenuti in modo che il player possa riprendere la riproduzione dei contenuti senza interruzioni.

Supporto degli annunci dichiarativi

Un URI del tag annuncio può essere specificato 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 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 media, URI dei contenuti 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 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 di annunci opaco con cui è collegato lo stato di riproduzione dell'annuncio per un determinato elemento multimediale, in base all'uguaglianza degli oggetti. Di seguito è riportato 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. Di conseguenza, gli annunci verranno caricati una sola volta e l'utente non vedrà annunci sul secondo elemento durante la riproduzione della 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 gli annunci definiti nella playlist HLS da inserire automaticamente sul lato client. Consulta la sezione relativa a HlsInterstitialsAdsLoader nella pagina HLS.

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

Per impostazione predefinita, PlayerView nasconde i controlli di trasporto durante la riproduzione degli annunci, ma le app possono attivare/disattivare questo comportamento chiamando setControllerHideDuringAds. L'SDK IMA mostrerà visualizzazioni aggiuntive sopra il player durante la riproduzione di un annuncio (ad esempio un link "Scopri di più" e un pulsante di avanzamento, se applicabile).

L'SDK IMA potrebbe segnalare se gli annunci sono oscurati 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à. Se utilizzi PlayerView come AdViewProvider, verranno 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 in 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. Pertanto, la riproduzione degli annunci autonomi non è supportata dalla libreria IMA. Per questo caso d'uso, consigliamo di utilizzare l'SDK Google Mobile Ads.

Utilizzo di un SDK pubblicitario 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 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 media contiene sia gli annunci sia i 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 il ImaServerSideAdInsertionMediaSource.AdsLoader e il 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 sorgente dei 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 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 negli "slot" dell'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.