Anzeigenbereitstellung

ExoPlayer kann sowohl für die clientseitige als auch für die serverseitige Anzeigenbereitstellung verwendet werden.

Clientseitige Anzeigenbereitstellung

Bei der clientseitigen Anzeigenbereitstellung wechselt der Player zwischen dem Laden der Medien beim Wechsel zwischen Content und Anzeigen unterschiedliche URLs. Informationen werden getrennt vom Medium geladen, etwa aus einem XML-VAST-Code oder VMAP-Anzeigen-Tag Dabei kann es sich um Cue-Positionen in Relation zum Anfang des die eigentlichen URIs und Metadaten der Anzeigenmedien, z. B. ob eine bestimmte Anzeige überspringbar.

Wenn AdsMediaSource von ExoPlayer für die clientseitige Anzeigenbereitstellung verwendet wird, enthält Informationen zu den wiederzugebenden Anzeigen. Dies hat mehrere Vorteile:

  • Der Player kann über seine API Metadaten und Funktionen für Anzeigen verfügbar machen.
  • Mit ExoPlayer-UI-Komponenten können automatisch Markierungen für Anzeigenpositionen angezeigt werden. und ihr Verhalten ändern, je nachdem, ob die Anzeige wiedergegeben wird oder nicht.
  • Intern kann der Player einen konsistenten Zwischenspeicher zwischen Übergängen Anzeigen und Content.

Dabei wechselt der Player zwischen Anzeigen und Content. bedeutet, dass Apps nicht mehrere separate Hintergrund-/Vordergrund-Playern für Anzeigen und Inhalte.

Wenn Sie Contentvideos und Anzeigen-Tags für die clientseitige Anzeigenbereitstellung vorbereiten, Anzeigen sollten idealerweise in Synchronisierungsbeispielen (Keyframes) im Content-Video an, damit der Player die Wiedergabe nahtlos fortsetzen kann.

Unterstützung deklarativer Anzeigen

Beim Erstellen eines MediaItem kann ein Anzeigen-Tag-URI angegeben werden:

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();

Damit Mediaelemente, die Anzeigen-Tags enthalten, im Player unterstützt werden, müssen Sie ein DefaultMediaSourceFactory erstellen und einfügen, das mit einem AdsLoader.Provider und AdViewProvider beim Erstellen des Players:

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();

Intern umschließt DefaultMediaSourceFactory die Content-Medienquelle in einem AdsMediaSource. AdsMediaSource erhält ein AdsLoader aus dem AdsLoader.Provider und verwenden Sie es zum Einfügen von Anzeigen, die in der Anzeige des Medienelements definiert sind. Tag.

PlayerView von ExoPlayer implementiert AdViewProvider. ExoPlayer-IMA Bibliothek ein einfach zu verwendendes AdsLoader zur Verfügung, wie unten beschrieben.

Playlists mit Werbung

Beim Abspielen einer Playlist mit mehreren Medienelementen ist das Standardverhalten: um für jede Media-ID das Anzeigen-Tag anzufordern und den Status der Anzeigenwiedergabe zu speichern, die Kombination aus Inhalts-URI und Anzeigen-Tag-URI. Nutzer sehen also Anzeigen für jedes Medienelement mit Anzeigen, die eine eigene Media-ID oder Content-URI haben, selbst wenn die Anzeigen-Tag-URIs übereinstimmen. Wenn ein Medienelement wiederholt wird, sieht der Nutzer das Element zugehörige Anzeigen nur einmal. Im Status der Anzeigenwiedergabe wird gespeichert, ob Anzeigen abgespielt werden, sodass sie beim ersten Mal übersprungen werden).

Sie können dieses Verhalten anpassen, indem Sie eine intransparente Anzeigen-ID übergeben. mit welchem Status der Anzeigenwiedergabe für ein bestimmtes Medienelement verknüpft ist, basierend auf dem Objekt und Gleichheit. Hier ist ein Beispiel, in dem der Status der Anzeigenwiedergabe mit dem Anzeigen-Tag verknüpft ist. und nicht die Kombination aus Media-ID und Anzeigen-Tag-URI, durch die und übergeben den URI des Anzeigen-Tags als Anzeigen-ID. Das hat zur Folge, dass die Anzeigen und der Nutzer sieht beim Abspielen des Videos Playlist von Anfang bis Ende.

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);

ExoPlayer-IMA-Bibliothek

Die ExoPlayer IMA-Bibliothek bietet ImaAdsLoader. Damit können Sie Integrieren Sie die clientseitige Anzeigenbereitstellung in Ihre App. Sie umfasst die Funktionen das clientseitige IMA SDK verwenden, um das Einfügen von VAST/VMAP-Anzeigen zu unterstützen. Für Anleitungen zur Verwendung der Bibliothek, einschließlich zum Umgang mit Hintergrundwiedergabe und die Fortsetzung der Wiedergabe finden Sie in der README-Datei.

Die Demoanwendung verwendet die IMA-Bibliothek und enthält mehrere VAST/VMAP-Anzeigen-Tags aus der Beispielliste.

Hinweise zur Benutzeroberfläche

PlayerView blendet während der Wiedergabe von Anzeigen die Transportsteuerelemente aus, indem Standardeinstellung, aber Apps können dieses Verhalten ändern, indem sie setControllerHideDuringAds. Mit dem IMA SDK werden zusätzliche Ansichten über während eine Anzeige wiedergegeben wird (z. B. ein "Weitere Infos"-Link und eine Schaltfläche "Überspringen", falls zutreffend).

Über das IMA SDK kann angegeben werden, ob Anzeigen durch von der Anwendung bereitgestellte Aufrufe verdeckt werden. die über dem Player gerendert werden. Apps, die Ansichten einblenden müssen, die für die Wiedergabe erforderlich sind, müssen sie beim IMA SDK registriert werden, können sie bei den Sichtbarkeitsberechnungen weggelassen werden. Bei Verwendung von PlayerView als die AdViewProvider enthält, werden automatisch ihre Kontroll-Overlays registriert. Apps die eine benutzerdefinierte Player-Benutzeroberfläche verwenden, müssen Overlay-Ansichten registrieren, indem sie AdViewProvider.getAdOverlayInfos

Weitere Informationen zu Overlay-Ansichten finden Sie unter Open Measurement im IMA SDK

Companion-Anzeigen

Einige Anzeigen-Tags enthalten zusätzliche Companion-Anzeigen, die in Anzeigenflächen erscheinen können. in einem in der App-Benutzeroberfläche. Diese Slots können über ImaAdsLoader.Builder.setCompanionAdSlots(slots) Weitere Informationen finden Sie unter Companion-Anzeigen hinzufügen

Eigenständige Anzeigen

Das IMA SDK ist für das Einfügen von Anzeigen in Medieninhalte vorgesehen, nicht zum Abspielen von Anzeigen. als eigenständige Anzeigen. Daher wird die Wiedergabe von eigenständigen Anzeigen nicht unterstützt. der IMA-Bibliothek enthalten. Wir empfehlen, stattdessen das Google Mobile Ads SDK zu verwenden. für diesen Anwendungsfall.

Mit dem Anzeigen-SDK eines Drittanbieters

Wenn Sie Anzeigen über das Anzeigen-SDK eines Drittanbieters laden müssen, sollten Sie prüfen, bereits eine ExoPlayer-Integration vorhanden ist. Falls nicht, implementieren Sie Der empfohlene Ansatz ist AdsLoader, der das Anzeigen-SDK des Drittanbieters umschließt. da es die oben beschriebenen Vorteile von AdsMediaSource bietet. ImaAdsLoader dient als Beispielimplementierung.

Alternativ kannst du die Playlist-Unterstützung von ExoPlayer nutzen, um eine Sequenz zu erstellen. von Anzeigen und Inhaltsclips:

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);

Serverseitige Anzeigenbereitstellung

Bei der serverseitigen Anzeigenbereitstellung, auch als dynamische Anzeigenbereitstellung bezeichnet, der Medienstream sowohl Anzeigen als auch Content enthält. Ein DASH-Manifest kann auf beides verweisen und Anzeigensegmente, möglicherweise in separaten Zeiträumen. Informationen zu HLS finden Sie in der Dokumentation zum Einbinden von Anzeigen in eine Playlist

Wenn Sie die serverseitige Anzeigenbereitstellung verwenden, muss der Client möglicherweise die Medien eine dynamische URL verwenden, um den Stitching-Stream zu erhalten, müssen möglicherweise Anzeigen-Overlays eingeblendet werden. oder Ereignisse an ein Anzeigen-SDK oder einen Ad-Server melden.

DefaultMediaSourceFactory von ExoPlayer kann alle diese Aufgaben an einen serverseitige Anzeigenbereitstellung MediaSource für URIs mit dem 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();

ExoPlayer-IMA-Bibliothek

Die ExoPlayer-IMA-Bibliothek stellt ImaServerSideAdInsertionMediaSource, mit denen sich die Integration der serverseitig eingefügten IMA-Anzeigen-Streams in Ihren Sie umfasst die Funktionen des IMA DAI SDK für Android integriert die bereitgestellten Anzeigenmetadaten in den Player. So können Sie z. B. Sie können Methoden wie Player.isPlayingAd() verwenden und Übergänge zwischen Inhalt und Anzeige beobachten. und der Player die Logik der Anzeigenwiedergabe wie das Überspringen bereits abgespielter Anzeigen verarbeitet.

Um diesen Kurs zu verwenden, müssen Sie den ImaServerSideAdInsertionMediaSource.AdsLoader und die ImaServerSideAdInsertionMediaSource.Factory und verbinde sie mit dem 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);

Laden Sie den IMA-Assetschlüssel oder die ID der Contentquelle und die Video-ID, indem Sie eine URL erstellen mit 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));

Geben Sie zum Schluss das Anzeigenladeprogramm frei, sobald es nicht mehr verwendet wird:

Kotlin

adsLoader.release()

Java

adsLoader.release();

Hinweise zur Benutzeroberfläche

Es gelten dieselben Überlegungen zur Benutzeroberfläche wie bei der clientseitigen Anzeigenbereitstellung serverseitige Anzeigenbereitstellung.

Companion-Anzeigen

Einige Anzeigen-Tags enthalten zusätzliche Companion-Anzeigen, die in Anzeigenflächen erscheinen können. in einem in der App-Benutzeroberfläche. Diese Slots können über ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots) Weitere Informationen finden Sie unter Companion-Anzeigen hinzufügen.

Mit dem Anzeigen-SDK eines Drittanbieters

Wenn Sie Anzeigen mit einem Drittanbieteranzeigen-SDK laden müssen, sollten Sie prüfen, bereits eine ExoPlayer-Integration vorhanden ist. Falls nicht, sollten Sie eine benutzerdefinierte MediaSource angeben, die URIs mit dem Schema ssai:// akzeptiert ähnlich wie ImaServerSideAdInsertionMediaSource.

Die eigentliche Logik zur Erstellung der Anzeigenstruktur kann an den allgemeinen Zweck ServerSideAdInsertionMediaSource, der einen Stream MediaSource umschließt Der Nutzer kann die AdPlaybackState für die Anzeige festlegen und aktualisieren. Metadaten.

Häufig enthalten serverseitig eingefügte Anzeigen-Streams zeitlich festgelegte Ereignisse, um den Player zu benachrichtigen. zu Anzeigenmetadaten. Unter Unterstützte Formate finden Sie Informationen dazu, Formate für zeitgesteuerte Metadaten werden von ExoPlayer unterstützt. SDK für benutzerdefinierte Anzeigen MediaSource -Implementierungen können zeitgesteuerte Metadaten-Ereignisse aus dem Player mithilfe von Player.Listener.onMetadata.