プレイリスト

再生リスト API は、すべての ExoPlayer 実装で実装される Player インターフェースによって定義されます。プレイリストを使用すると、複数のメディア アイテムを順番に再生できます。次の例は、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 に加えて、カスタムタグ(アプリ提供の任意のオブジェクト)を使用して各メディア アイテムを構成することもできます。カスタムタグの用途の一つは、各メディア アイテムにメタデータを適用することです。

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_CHANGEDListener.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 が呼び出されます。他にも、以下のような理由でタイムラインが更新されます。

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