プレイリスト

プレイリスト API は Player インターフェースで定義され、すべての ExoPlayer 実装によって実装されます。プレイリストを使用すると、複数のメディア アイテムを順次再生できます。次の例は、2 つの動画を含む再生リストの再生を開始する方法を示しています。

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

プレイリスト内のアイテム間の遷移はシームレスです。同じ形式である必要はありません(たとえば、再生リストに H264 動画と VP9 動画の両方を含めることは問題ありません)。異なるタイプでもかまいません(つまり、動画、画像、音声のみのストリームを再生リストに含めてもかまいません)。同じ MediaItem を再生リスト内で複数回使用できます。

再生リストを変更する

メディア アイテムを追加、移動、削除、置換することで、再生リストを動的に変更できます。これは、再生前と再生中の両方で、対応するプレイリスト API メソッドを呼び出すことで行えます。

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

プレイリスト全体の置換とクリアもサポートされています。

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

プレーヤーは、再生中の変更を正しい方法で自動的に処理します。

  • 現在再生中の MediaItem が移動された場合、再生は中断されず、完了すると新しい後継が再生されます。
  • 現在再生中の MediaItem が削除されると、プレーヤーは残りの最初の後継を自動的に再生します。そのような後継が存在しない場合は、終了状態に移行します。
  • 現在再生中の MediaItem が置き換えられた場合、再生に関連する MediaItem のプロパティが変更されていない限り、再生は中断されません。たとえば、ほとんどの場合、再生に影響を与えることなく MediaItem.MediaMetadata フィールドを更新できます。

再生リストのクエリ

再生リストは Player.getMediaItemCountPlayer.getMediaItemAt を使用してクエリできます。現在再生中のメディア アイテムは、Player.getCurrentMediaItem を呼び出してクエリできます。プレイリスト内のナビゲーションを簡素化するための Player.hasNextMediaItemPlayer.getNextMediaItemIndex などの便利なメソッドもあります。

繰り返しモード

プレーヤーは 3 つの繰り返しモードをサポートしており、Player.setRepeatMode でいつでも設定できます。

  • Player.REPEAT_MODE_OFF: 再生リストは繰り返されず、再生リスト内の最後のアイテムが再生されると、プレーヤーは Player.STATE_ENDED に移行します。
  • Player.REPEAT_MODE_ONE: 現在のアイテムが無限ループで繰り返されます。Player.seekToNextMediaItem などのメソッドはこれを無視し、リスト内の次のアイテムにシークします。この処理は、無限ループで繰り返されます。
  • Player.REPEAT_MODE_ALL: 再生リスト全体が無限ループで繰り返されます。

シャッフル モード

シャッフル モードは、Player.setShuffleModeEnabled を使用していつでも有効または無効にできます。シャッフル モードでは、事前に計算されたランダムな順序でプレイリストが再生されます。すべてのアイテムが 1 回再生されます。シャッフル モードは Player.REPEAT_MODE_ALL と組み合わせて、無限ループで同じランダムな順序を繰り返すこともできます。シャッフル モードをオフにすると、再生は再生リスト内の元の位置にある現在のアイテムから続行されます。

Player.getCurrentMediaItemIndex などのメソッドから返されるインデックスは、常に元のシャッフルされていない順序を参照することに注意してください。同様に、Player.seekToNextMediaItemplayer.getCurrentMediaItemIndex() + 1 のアイテムではなく、シャッフル順序に従って次のアイテムを再生します。プレイリストに新しいアイテムを挿入したり、アイテムを削除したりしても、既存のシャッフル順序は可能な限り変更されません。

カスタムのシャッフル順序を設定する

デフォルトでは、プレーヤーは DefaultShuffleOrder を使用してシャッフルをサポートしています。 これは、カスタム シャッフル順序の実装を指定するか、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);

再生リストのアイテムの特定

再生リストのアイテムを識別するには、アイテムのビルド時に MediaItem.mediaId を設定します。

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

アプリがメディア アイテムのメディア ID を明示的に定義していない場合、URI の文字列表現が使用されます。

アプリデータとプレイリスト アイテムの関連付け

各メディア アイテムには、ID に加えてカスタムタグを設定することもできます。カスタムタグには、アプリが提供する任意のオブジェクトを使用できます。カスタムタグの 1 つの用途は、各メディア アイテムにメタデータを関連付けることです。

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

再生が別のメディア アイテムに遷移するタイミングを検出する

再生が別のメディア アイテムに移行した場合や、同じメディア アイテムの繰り返しが開始された場合、Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason) が呼び出されます。このコールバックは、新しいメディア アイテムと、遷移が発生した理由を示す @MediaItemTransitionReason を受け取ります。onMediaItemTransition の一般的なユースケースは、新しいメディア アイテム用にアプリの UI を更新することです。

Kotlin

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

Java

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

UI の更新に必要なメタデータがカスタムタグを使用して各メディア アイテムに添付されている場合、実装は次のようになります。

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

再生リストの変更を検出する

メディア アイテムが追加、削除、移動されると、TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED と同時に Listener.onTimelineChanged(Timeline, @TimelineChangeReason) が呼び出されます。このコールバックは、プレーヤーがまだ準備されていない場合でも呼び出されます。

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

プレイリスト内のメディア アイテムの長さなどの情報が利用可能になると、Timeline が更新され、TIMELINE_CHANGE_REASON_SOURCE_UPDATEonTimelineChanged が呼び出されます。タイムラインの更新につながるその他の理由には、次のようなものがあります。

  • アダプティブ メディア アイテムの準備後に利用可能になるマニフェスト。
  • ライブ配信の再生中に定期的に更新されるマニフェスト。