プレイリスト

プレイリスト 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_UPDATE を使用して onTimelineChanged が呼び出されます。タイムラインの更新がトリガーされるその他の理由としては、次のようなものがあります。

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