トラックの選択

メディア アイテムに複数のトラックが含まれている場合、トラック選択は、再生するトラックを決定するプロセスです。トラック選択プロセスは TrackSelectionParameters によって構成されます。これにより、トラック選択に影響するさまざまな制約とオーバーライドを指定できます。

利用可能なトラックのクエリ

Player.Listener.onTracksChanged をリッスンすると、トラックの変更に関する通知を受け取ることができます。たとえば、次のような変更です。

  • 再生中のメディア アイテムの準備が完了したときに、利用可能なトラックがわかる。プレーヤーは、メディア アイテムに含まれるトラックを把握するために、メディア アイテムを準備する必要があります。
  • 再生が 1 つのメディア アイテムから別のメディア アイテムに移行したため、利用可能なトラックが変更された。
  • 選択したトラックに対する変更。

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTracksChanged(tracks: Tracks) {
      // Update UI using current tracks.
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTracksChanged(Tracks tracks) {
        // Update UI using current tracks.
      }
    });

player.getCurrentTracks() を呼び出して、現在のトラックをクエリすることもできます。返される Tracks には Tracks.Group オブジェクトのリストが含まれます。単一の Group 内のトラックは同じコンテンツを異なる形式で表します。

トラックをグループ化する方法の例として、メインの動画フィードが 5 つのビットレートで提供され、代替の動画フィード(スポーツの試合の別のカメラアングルなど)が 2 つのビットレートで提供されるアダプティブ再生を考えてみましょう。この場合、2 つの動画トラック グループが存在します。1 つは 5 つのトラックを含むメインの動画フィードに対応し、もう 1 つは 2 つのトラックを含む代替の動画フィードに対応します。

言語が異なる音声トラックはグループ化されません。言語が異なるコンテンツは同じものとは見なされないためです。逆に、ビットレート、サンプリング レート、チャンネル数などのプロパティのみが異なる同じ言語の音声トラックはグループ化できます。これはテキスト トラックにも適用されます。

Group をクエリして、再生がサポートされているトラック、現在選択されているトラック、各トラックが使用する Format を特定できます。

Kotlin

for (trackGroup in tracks.groups) {
  // Group level information.
  val trackType = trackGroup.type
  val trackInGroupIsSelected = trackGroup.isSelected
  val trackInGroupIsSupported = trackGroup.isSupported
  for (i in 0 until trackGroup.length) {
    // Individual track information.
    val isSupported = trackGroup.isTrackSupported(i)
    val isSelected = trackGroup.isTrackSelected(i)
    val trackFormat = trackGroup.getTrackFormat(i)
  }
}

Java

for (Tracks.Group trackGroup : tracks.getGroups()) {
  // Group level information.
  @C.TrackType int trackType = trackGroup.getType();
  boolean trackInGroupIsSelected = trackGroup.isSelected();
  boolean trackInGroupIsSupported = trackGroup.isSupported();
  for (int i = 0; i < trackGroup.length; i++) {
    // Individual track information.
    boolean isSupported = trackGroup.isTrackSupported(i);
    boolean isSelected = trackGroup.isTrackSelected(i);
    Format trackFormat = trackGroup.getTrackFormat(i);
  }
}
  • Player がトラックのサンプルをデコードしてレンダリングできる場合、そのトラックはサポートされていることになります。同じタイプの複数のトラック グループ(複数の音声トラック グループなど)がサポートされている場合でも、それらは個別にサポートされているだけであり、プレーヤーがそれらを同時に再生できるとは限りません。
  • 現在の TrackSelectionParameters が指定されたときに再生用に選択されたトラックは、選択済みです。1 つのトラック グループ内の複数のトラックが選択されている場合、プレーヤーはこれらのトラックをアダプティブ再生に使用します(たとえば、ビットレートの異なる複数の動画トラック)。一度に再生されるのはこれらのトラックのいずれか 1 つのみです。

トラック選択パラメータの変更

トラック選択プロセスは、Player.setTrackSelectionParameters を使用して構成できます。この操作は、再生前と再生中の両方で行うことができます。次の例は、プレーヤーから現在の TrackSelectionParameters を取得し、それらを変更して、変更した結果で Player を更新する方法を示しています。

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setMaxVideoSizeSd()
    .setPreferredAudioLanguage("hu")
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setMaxVideoSizeSd()
        .setPreferredAudioLanguage("hu")
        .build());

制約ベースのトラック選択

TrackSelectionParameters のほとんどのオプションでは、実際に利用可能なトラックとは独立した制約を指定できます。使用可能な制約は次のとおりです。

  • 動画の最大幅、最小幅、最大高さ、最小高さ、最大フレームレート、最小フレームレート、最大ビットレート、最小ビットレート。
  • 音声チャンネルの最大数とビットレート。
  • 動画と音声の優先 MIME タイプ。
  • 優先する音声言語と役割フラグ。
  • 優先するテキスト言語とロールフラグ。

ExoPlayer は、これらの制約に適切なデフォルトを使用します。たとえば、動画の解像度をディスプレイ サイズに制限したり、ユーザーのシステム ロケール設定に一致する音声言語を優先したりします。

利用可能なトラックから特定のトラックを選択するのではなく、制約ベースのトラック選択を使用することには、次のようなメリットがあります。

  • メディア アイテムが提供するトラックがわからなくても、制約を指定できます。つまり、制約はプレーヤーがメディア アイテムを準備する前に指定できますが、特定のトラックを選択するには、利用可能なトラックがわかるまでアプリケーション コードで待機する必要があります。
  • 制約は、プレイリスト内のすべてのメディア アイテムに適用されます。アイテムごとに利用可能なトラックが異なる場合でも同様です。たとえば、優先音声言語の制約は、その言語のトラックの Format がメディア アイテムごとに異なっていても、すべてのメディア アイテムに自動的に適用されます。特定のトラックを選択する場合は、以下の説明のとおり、このようにはなりません。

特定のトラックを選択する

TrackSelectionParameters を使用して特定のトラックを選択できます。まず、Player.getCurrentTracks を使用して、プレーヤーで現在利用可能なトラックをクエリする必要があります。次に、選択するトラックを特定したら、TrackSelectionOverride を使用して TrackSelectionParameters に設定できます。たとえば、特定の audioTrackGroup から最初のトラックを選択するには:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setOverrideForType(
      TrackSelectionOverride(audioTrackGroup.mediaTrackGroup, /* trackIndex= */ 0)
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setOverrideForType(
            new TrackSelectionOverride(
                audioTrackGroup.getMediaTrackGroup(), /* trackIndex= */ 0))
        .build());

TrackSelectionOverride は、オーバーライドで指定されたものと完全に一致する TrackGroup を含むメディア アイテムにのみ適用されます。そのため、異なるトラックが含まれているメディア アイテムにはオーバーライドが適用されない場合があります。

トラックタイプまたはグループを無効にする

動画、音声、テキストなどのトラックタイプは、TrackSelectionParameters.Builder.setTrackTypeDisabled を使用して完全に無効にできます。無効なトラックタイプは、すべてのメディア アイテムで無効になります。

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
        .build());

また、特定の TrackGroup からのトラックの選択を禁止するには、そのグループのオーバーライドを空で指定します。

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .addOverride(
      TrackSelectionOverride(disabledTrackGroup.mediaTrackGroup, /* trackIndices= */ listOf())
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .addOverride(
            new TrackSelectionOverride(
                disabledTrackGroup.getMediaTrackGroup(),
                /* trackIndices= */ ImmutableList.of()))
        .build());

トラック セレクタをカスタマイズする

トラックの選択は TrackSelector の責任です。ExoPlayer がビルドされるたびに TrackSelector のインスタンスが提供され、後で ExoPlayer.getTrackSelector() で取得できます。

Kotlin

val trackSelector = DefaultTrackSelector(context)
val player = ExoPlayer.Builder(context).setTrackSelector(trackSelector).build()

Java

DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
ExoPlayer player = new ExoPlayer.Builder(context).setTrackSelector(trackSelector).build();

DefaultTrackSelector は、ほとんどのユースケースに適した柔軟な TrackSelector です。Player で設定された TrackSelectionParameters を使用しますが、DefaultTrackSelector.ParametersBuilder で指定できる高度なカスタマイズ オプションもいくつか提供します。

Kotlin

trackSelector.setParameters(
  trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true)
)

Java

trackSelector.setParameters(
    trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true));

トンネリング

トンネリングは、一部のテレビ デバイスで高解像度ストリームの動画を効率的に再生するのに役立ちます。その他の注意事項と詳細については、バッテリー消費量のページをご覧ください。

トンネル再生の設定を行うと、レンダラと選択したトラックの組み合わせがトンネル再生をサポートしている場合に、トンネル再生が有効になります。これを行うには、DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true) を使用します。

オーディオ オフロード

オーディオ オフロードは、特に画面をオフにした状態での長時間再生で、電力を節約するのに役立ちます。詳細については、バッテリー消費量のページをご覧ください。

オフロードされた音声再生の設定を行うことで、レンダラと選択されたトラックの組み合わせがオフロードされた音声再生をサポートしている場合に、オフロードされた音声再生を有効にできます。これを行うには、TrackSelectionParametersAudioOffloadModePreferences を指定します。

Kotlin

val audioOffloadPreferences =
  AudioOffloadPreferences.Builder()
    .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
    // Add additional options as needed
    .setIsGaplessSupportRequired(true)
    .build()
player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setAudioOffloadPreferences(audioOffloadPreferences)
    .build()

Java

AudioOffloadPreferences audioOffloadPreferences =
    new AudioOffloadPreferences.Builder()
        .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
        // Add additional options as needed
        .setIsGaplessSupportRequired(true)
        .build();
player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setAudioOffloadPreferences(audioOffloadPreferences)
        .build());