Playlists

L'API de playlist est définie par l'interface Player, qui est implémentée par toutes les implémentations de ExoPlayer. Les playlists permettent la lecture séquentielle de plusieurs éléments multimédias. L'exemple suivant montre comment lancer la lecture d'une playlist contenant deux vidéos:

Kotlin

// Build the media items.
val firstItem = MediaItem.fromUri(firstVideoUri)
val secondItem = MediaItem.fromUri(secondVideoUri)
// Add the media items to be played.
player.addMediaItem(firstItem)
player.addMediaItem(secondItem)
// Prepare the player.
player.prepare()
// Start the playback.
player.play()

Java

// Build the media items.
MediaItem firstItem = MediaItem.fromUri(firstVideoUri);
MediaItem secondItem = MediaItem.fromUri(secondVideoUri);
// Add the media items to be played.
player.addMediaItem(firstItem);
player.addMediaItem(secondItem);
// Prepare the player.
player.prepare();
// Start the playback.
player.play();

Les transitions entre les éléments d'une playlist sont fluides. Il n'est pas nécessaire qu'elles soient du même format (par exemple, une playlist peut contenir à la fois des vidéos H264 et VP9). Ils peuvent même être de types différents (c'est-à-dire qu'une playlist peut contenir à la fois des flux vidéo et audio uniquement). Vous pouvez utiliser le même MediaItem plusieurs fois dans une playlist.

Modifier la playlist

Vous pouvez modifier une playlist de manière dynamique en ajoutant, déplaçant, supprimant ou remplaçant des éléments multimédias. Vous pouvez le faire avant et pendant la lecture en appelant les méthodes de l'API de playlist correspondantes:

Kotlin

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri))
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0)
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0)
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri))

Java

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri));
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0);
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0);
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri));

Vous pouvez également remplacer et effacer toute la playlist:

Kotlin

// Replaces the playlist with a new one.
val newItems: List<MediaItem> = listOf(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri))
player.setMediaItems(newItems, /* resetPosition= */ true)
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems()

Java

// Replaces the playlist with a new one.
ImmutableList<MediaItem> newItems =
    ImmutableList.of(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri));
player.setMediaItems(newItems, /* resetPosition= */ true);
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems();

Le lecteur gère automatiquement les modifications lors de la lecture de la bonne manière:

  • Si l'élément MediaItem en cours de lecture est déplacé, la lecture n'est pas interrompue et le nouveau successeur est lu une fois la lecture terminée.
  • Si le MediaItem en cours de lecture est supprimé, le lecteur lit automatiquement le premier successeur restant ou passe à l'état terminé en l'absence de successeur de ce type.
  • Si l'élément MediaItem en cours de lecture est remplacé, la lecture n'est pas interrompue si aucune des propriétés de l'élément MediaItem correspondant à la lecture n'a été modifiée. Par exemple, dans la plupart des cas, il est possible de mettre à jour les champs MediaItem.MediaMetadata sans affecter la lecture.

Interroger la playlist

Vous pouvez interroger la playlist à l'aide de Player.getMediaItemCount et Player.getMediaItemAt. Vous pouvez interroger l'élément multimédia en cours de lecture en appelant Player.getCurrentMediaItem. Il existe également d'autres méthodes pratiques, telles que Player.hasNextMediaItem ou Player.getNextMediaItemIndex, pour simplifier la navigation dans la playlist.

Modes de répétition

Le lecteur accepte trois modes de répétition qui peuvent être définis à tout moment avec Player.setRepeatMode:

  • Player.REPEAT_MODE_OFF: la playlist n'est pas répétée, et le lecteur passe à Player.STATE_ENDED une fois le dernier élément de la playlist lu.
  • Player.REPEAT_MODE_ONE: l'élément actuel est répété dans une boucle sans fin. Les méthodes telles que Player.seekToNextMediaItem ignorent cela et recherchent l'élément suivant de la liste, qui sera ensuite répété dans une boucle sans fin.
  • Player.REPEAT_MODE_ALL: toute la playlist est répétée en boucle sans fin.

Mode aléatoire

Le mode aléatoire peut être activé ou désactivé à tout moment à l'aide de Player.setShuffleModeEnabled. En mode aléatoire, le lecteur lit la playlist dans un ordre aléatoire précalculé. Tous les éléments sont lus une fois. Le mode aléatoire peut également être combiné avec Player.REPEAT_MODE_ALL pour répéter le même ordre aléatoire dans une boucle sans fin. Lorsque le mode aléatoire est désactivé, la lecture reprend à partir de l'élément en cours à sa position d'origine dans la playlist.

Notez que les index renvoyés par des méthodes telles que Player.getCurrentMediaItemIndex font toujours référence à l'ordre d'origine sans brassage. De même, Player.seekToNextMediaItem ne lit pas l'élément player.getCurrentMediaItemIndex() + 1, mais l'élément suivant en fonction de l'ordre de brassage. L'insertion de nouveaux éléments dans la playlist ou la suppression d'éléments conservent, dans la mesure du possible, l'ordre aléatoire existant.

Définir un ordre de lecture aléatoire personnalisé

Par défaut, le lecteur prend en charge la lecture en mode aléatoire à l'aide de DefaultShuffleOrder. Vous pouvez personnaliser cet ordre en fournissant une implémentation personnalisée de l'ordre de brassage ou en définissant un ordre personnalisé dans le constructeur DefaultShuffleOrder:

Kotlin

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(DefaultShuffleOrder(intArrayOf(3, 1, 0, 4, 2), randomSeed))
// Enable shuffle mode.
exoPlayer.shuffleModeEnabled = true

Java

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(new DefaultShuffleOrder(new int[] {3, 1, 0, 4, 2}, randomSeed));
// Enable shuffle mode.
exoPlayer.setShuffleModeEnabled(/* shuffleModeEnabled= */ true);

Identifier les éléments d'une playlist

Pour identifier les éléments de la playlist, MediaItem.mediaId peut être défini lors de la création de l'élément:

Kotlin

// Build a media item with a media ID.
val mediaItem = MediaItem.Builder().setUri(uri).setMediaId(mediaId).build()

Java

// Build a media item with a media ID.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setMediaId(mediaId).build();

Si une application ne définit pas explicitement d'ID multimédia pour un élément multimédia, la représentation sous forme de chaîne de l'URI est utilisée.

Associer des données d'application à des éléments de playlist

En plus d'un ID, chaque élément multimédia peut également être configuré avec une balise personnalisée, qui peut être n'importe quel objet fourni par l'application. Les tags personnalisés permettent d'associer des métadonnées à chaque élément multimédia:

Kotlin

// Build a media item with a custom tag.
val mediaItem = MediaItem.Builder().setUri(uri).setTag(metadata).build()

Java

// Build a media item with a custom tag.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setTag(metadata).build();

Détecter quand la lecture passe à un autre élément multimédia

Lorsque la lecture passe à un autre élément multimédia ou commence à répéter le même élément multimédia, Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason) est appelé. Ce rappel reçoit le nouvel élément multimédia, avec un @MediaItemTransitionReason indiquant la raison de la transition. Un cas d'utilisation courant de onMediaItemTransition consiste à mettre à jour l'UI de l'application pour le nouvel élément multimédia:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  updateUiForPlayingMediaItem(mediaItem)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  updateUiForPlayingMediaItem(mediaItem);
}

Si les métadonnées requises pour mettre à jour l'interface utilisateur sont associées à chaque élément multimédia à l'aide de balises personnalisées, l'implémentation peut se présenter comme suit:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  var metadata: CustomMetadata? = null
  mediaItem?.localConfiguration?.let { localConfiguration ->
    metadata = localConfiguration.tag as? CustomMetadata
  }
  updateUiForPlayingMediaItem(metadata)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  @Nullable CustomMetadata metadata = null;
  if (mediaItem != null && mediaItem.localConfiguration != null) {
    metadata = (CustomMetadata) mediaItem.localConfiguration.tag;
  }
  updateUiForPlayingMediaItem(metadata);
}

Détecter quand la playlist change

Lorsqu'un élément multimédia est ajouté, supprimé ou déplacé, Listener.onTimelineChanged(Timeline, @TimelineChangeReason) est appelé immédiatement avec TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED. Ce rappel est appelé même lorsque le joueur n'a pas encore été préparé.

Kotlin

override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
  if (reason == Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline)
  }
}

Java

@Override
public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
  if (reason == TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline);
  }
}

Lorsque des informations telles que la durée d'un élément multimédia de la playlist deviennent disponibles, Timeline est mis à jour et onTimelineChanged est appelé avec TIMELINE_CHANGE_REASON_SOURCE_UPDATE. Voici d'autres raisons pouvant entraîner une mise à jour de la chronologie:

  • Fichier manifeste disponible après la préparation d'un élément multimédia adaptatif.
  • Fichier manifeste mis à jour régulièrement lors de la lecture d'une diffusion en direct.