Inserimento degli annunci

ExoPlayer può essere utilizzato per l'inserimento di annunci sia lato client che lato server.

Inserimento di annunci lato client

Nell'inserimento di annunci lato client, il player passa dal caricamento di contenuti multimediali a un URL diverso durante la transizione dalla riproduzione dei contenuti agli annunci e viceversa. Le informazioni sugli annunci vengono caricate separatamente dal contenuto multimediale, ad esempio da un tag annuncio XML VAST o VMAP. Questi dati possono includere le posizioni dei segnali dell'annuncio rispetto all'inizio dei contenuti, gli effettivi URI dei contenuti multimediali degli annunci 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 delle informazioni sugli annunci da riprodurre. Ciò 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 indicatori per le posizioni degli annunci e modificarne il comportamento a seconda che l'annuncio venga riprodotto o meno.
  • Internamente, il player può mantenere un buffer coerente tra le transizioni tra gli annunci e i contenuti.

In questa configurazione, il player si occupa di alternare gli annunci e i contenuti, il che significa che le app non devono occuparsi del controllo di più player separati in background/in primo piano per annunci e contenuti.

Durante la preparazione dei video di contenuti e dei tag annuncio da utilizzare con l'inserimento di annunci lato client, gli annunci dovrebbero essere posizionati in corrispondenza degli esempi di sincronizzazione (fotogrammi chiave) nel video dei contenuti, in modo che il player possa riprendere la riproduzione dei contenuti senza problemi.

Supporto dichiarativo degli annunci

È possibile specificare l'URI di un 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 tag annuncio, è necessario creare e inserire un DefaultMediaSourceFactory configurato con AdsLoader.Provider e 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 aggrega l'origine multimediale dei contenuti in un AdsMediaSource. L'elemento AdsMediaSource otterrà un valore 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 offre uno strumento AdsLoader facile da usare, come descritto di seguito.

Playlist con annunci

Quando riproduci una playlist con più elementi multimediali, il comportamento predefinito è quello di richiedere il tag annuncio e memorizzare lo stato di riproduzione dell'annuncio una volta per ogni combinazione di ID elemento multimediale, URI contenuti e URI tag annuncio. Ciò significa che gli utenti vedranno annunci per ogni elemento multimediale con annunci che hanno un ID elemento multimediale o un URI di contenuti distinto, anche se gli URI del 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, in modo che vengano ignorati dopo la prima occorrenza).

È possibile personalizzare questo comportamento passando un identificatore annunci opachi a cui è collegato lo stato di riproduzione dell'annuncio per un determinato elemento multimediale, in base all'uguaglianza dell'oggetto. Di seguito è riportato un esempio in cui lo stato di riproduzione dell'annuncio è collegato solo all'URI del tag annuncio, anziché alla combinazione di ID multimediale e URI del tag annuncio, trasmettendo l'URI del tag annuncio come identificatore 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);

Raccolta IMA di ExoPlayer

La libreria IMA di ExoPlayer fornisce ImaAdsLoader, semplificando l'integrazione dell'inserimento di annunci lato client nella tua app. Integra la funzionalità dell'SDK IMA lato client per supportare l'inserimento di annunci VAST/VMAP. Per istruzioni su come utilizzare la libreria, incluse informazioni su come gestire la riproduzione in background e riprendere la riproduzione, consulta il file README.

L'applicazione demo utilizza la libreria IMA e include diversi tag annuncio VAST/VMAP di esempio nell'elenco.

Considerazioni relative all'interfaccia utente

Per impostazione predefinita, PlayerView nasconde i propri controlli di trasporto durante la riproduzione degli annunci, ma le app possono attivare/disattivare questo comportamento chiamando setControllerHideDuringAds. L'SDK IMA mostrerà visualizzazioni aggiuntive nella parte superiore del player durante la riproduzione di un annuncio (ad esempio, un link "Ulteriori informazioni" e un pulsante Salta, se applicabile).

L'SDK IMA potrebbe segnalare se gli annunci sono oscurati dalle visualizzazioni fornite dall'applicazione visualizzate nella parte superiore del player. Le app che devono sovrapporre le viste essenziali per il controllo della riproduzione devono registrarle nell'SDK IMA in modo che possano essere omesse dai calcoli della visibilità. Quando utilizzi PlayerView come AdViewProvider, vengono registrati automaticamente gli overlay di controllo. Le app che utilizzano un'interfaccia utente del player personalizzato devono registrare le visualizzazioni 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 dell'app. Questi slot possono essere trasmessi tramite ImaAdsLoader.Builder.setCompanionAdSlots(slots). Per ulteriori informazioni, consulta la sezione Aggiunta di annunci companion.

Annunci autonomi

L'SDK IMA è progettato per l'inserimento di annunci nei contenuti multimediali, non per la riproduzione di 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.

Utilizzare un SDK per gli annunci di terze parti

Se devi caricare gli annunci tramite un SDK per gli annunci di terze parti, verifica se fornisce già un'integrazione ExoPlayer. In caso contrario, l'implementazione di un elemento AdsLoader personalizzato che aggrega l'SDK per gli annunci di terze parti è l'approccio consigliato, poiché offre i vantaggi di AdsMediaSource descritti sopra. ImaAdsLoader funge da implementazione di esempio.

In alternativa, puoi utilizzare il supporto della 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 include sia annunci che contenuti. Un file manifest DASH può indirizzare sia contenuti che a segmenti di annunci, possibilmente in periodi distinti. Per HLS, consulta la documentazione di Apple su come incorporare annunci in una playlist.

Quando si utilizza l'inserimento di annunci lato server, il cliente potrebbe dover risolvere l'URL multimediale in modo dinamico per ottenere lo stream unito, visualizzare gli overlay degli annunci nell'interfaccia utente o segnalare gli eventi a un SDK per gli annunci o ad un ad server.

DefaultMediaSourceFactory di ExoPlayer può delegare tutte queste attività a un inserimento 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();

Raccolta IMA di ExoPlayer

La libreria IMA di ExoPlayer fornisce ImaServerSideAdInsertionMediaSource, semplificando l'integrazione con gli stream di annunci inseriti lato server di IMA nella tua app. Integra la funzionalità dell'SDK IMA DAI per Android e integra completamente i metadati degli annunci forniti nel player. In questo modo, ad esempio, puoi utilizzare metodi come Player.isPlayingAd(), ascoltare le transizioni di contenuti e gli annunci e lasciare che il player gestisca la logica di riproduzione degli annunci, ad esempio saltare gli annunci già riprodotti.

Per utilizzare questa lezione, 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 di annunci quando non viene più utilizzato:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Considerazioni relative all'interfaccia utente

Per l'inserimento di annunci lato server si applicano le stesse considerazioni relative all'interfaccia utente previste 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 dell'app. Questi slot possono essere trasmessi tramite ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots). Per ulteriori informazioni, consulta la sezione Aggiunta di annunci companion.

Utilizzare un SDK per gli annunci di terze parti

Se devi caricare gli annunci utilizzando un SDK per gli annunci di terze parti, verifica se fornisce già un'integrazione ExoPlayer. In caso contrario, ti consigliamo di fornire un elemento MediaSource personalizzato che accetti URI con lo schema ssai:// simile a ImaServerSideAdInsertionMediaSource.

La logica effettiva per la creazione della struttura dell'annuncio può essere delegata all'oggetto ServerSideAdInsertionMediaSource per uso generico, che aggrega un flusso MediaSource e consente all'utente di impostare e aggiornare il AdPlaybackState che rappresenta i metadati degli annunci.

Spesso, gli stream di annunci inseriti lato server contengono eventi a tempo che informano il player dei metadati degli annunci. Consulta i formati supportati per informazioni su quali formati di metadati temporali sono supportati da ExoPlayer. Le implementazioni dell'SDK per gli annunci personalizzati MediaSource possono ascoltare gli eventi di metadati a tempo del player utilizzando Player.Listener.onMetadata.