Playlists

L'API de playlist est définie par l'interface Player, qui est implémentée par toutes les implémentations 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 au même format (par exemple, une playlist peut contenir des vidéos H264 et VP9). Ils peuvent même être de différents types (par exemple, une playlist peut contenir des vidéos, des images et des flux audio uniquement). Vous pouvez utiliser le même MediaItem plusieurs fois dans une playlist.

Modifier la playlist

Vous pouvez modifier dynamiquement une playlist en ajoutant, déplaçant, supprimant ou remplaçant des éléments multimédias. Vous pouvez effectuer cette opération avant et pendant la lecture en appelant les méthodes d'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));

Le remplacement et l'effacement de l'intégralité de la playlist sont également possibles :

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 pendant la lecture de la manière suivante :

  • Si le MediaItem en cours de lecture est déplacé, la lecture n'est pas interrompue et le nouveau successeur est lu à la fin.
  • Si le MediaItem en cours de lecture est supprimé, le lecteur lit automatiquement le premier successeur restant ou passe à l'état "ended" (terminé) si aucun successeur n'existe.
  • Si le MediaItem en cours de lecture est remplacé, la lecture n'est pas interrompue si aucune des propriétés du MediaItem concerné par la lecture n'a changé. Par exemple, il est possible de mettre à jour les champs MediaItem.MediaMetadata dans la plupart des cas sans affecter la lecture.

Interroger la playlist

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

Modes de répétition

Le lecteur est compatible avec 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 que le dernier élément de la playlist a été lu.
  • Player.REPEAT_MODE_ONE : l'élément actuel est répété en boucle. Les méthodes telles que Player.seekToNextMediaItem ignoreront cette valeur et passeront à l'élément suivant de la liste, qui sera ensuite répété en boucle.
  • Player.REPEAT_MODE_ALL : la playlist entière est lue en boucle.

Mode aléatoire

Vous pouvez activer ou désactiver le mode aléatoire à tout moment avec Player.setShuffleModeEnabled. En mode aléatoire, le lecteur lit la playlist dans un ordre aléatoire précalculé. Tous les éléments seront 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 en boucle. Lorsque le mode aléatoire est désactivé, la lecture se poursuit à partir de l'élément actuel, à 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 non aléatoire. De même, Player.seekToNextMediaItem ne lira pas l'élément à player.getCurrentMediaItemIndex() + 1, mais l'élément suivant selon l'ordre aléatoire. Si vous insérez ou supprimez des éléments dans la playlist, l'ordre aléatoire existant est conservé autant que possible.

Définir un ordre aléatoire personnalisé

Par défaut, le lecteur prend en charge la lecture aléatoire à l'aide de DefaultShuffleOrder. Vous pouvez personnaliser cet ordre en fournissant une implémentation d'ordre aléatoire personnalisé 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 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 de contenu 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 un tag personnalisé, qui peut être n'importe quel objet fourni par l'application. Les tags personnalisés peuvent être utilisés pour 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étection du moment où 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, ainsi qu'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'UI sont associées à chaque élément multimédia à l'aide de tags personnalisés, une 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 les modifications apportées à la playlist

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 lecteur 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 qui peuvent entraîner une mise à jour de votre timeline :

  • Un fichier manifeste devient disponible après la préparation d'un élément multimédia adaptatif.
  • Un fichier manifeste est mis à jour régulièrement pendant la lecture d'une diffusion en direct.