カスタマイズ

ExoPlayer ライブラリの中核は Player インターフェースです。Player 従来のハイレベルなメディア プレーヤーの機能をエクスポーズします。たとえば、 メディアのバッファリング、再生、一時停止、移動を行います。デフォルトの実装 ExoPlayer は次のとおりです。 前提がほとんどない(そのため制限がほとんどない)ように設計されている 再生中のメディアの種類、保存方法、保存場所、 表示されます。メディアの読み込みとレンダリングを直接実装するのではなく、 ExoPlayer 実装は、注入されるコンポーネントにこの作業を委任します。 プレーヤーの作成時、または新しいメディアソースがプレーヤーに渡されるとき。 すべての ExoPlayer 実装に共通するコンポーネントは次のとおりです。

  • 再生するメディアを定義する MediaSource インスタンス、メディアを読み込むインスタンス、 読み込まれたメディアの読み取りが可能になります。MediaSource インスタンスが作成されます プレーヤー内の MediaSource.Factory による MediaItem から。また、 メディアソース ベースの再生リスト API を使用してプレーヤーに直接渡す。
  • MediaItemMediaSource に変換する MediaSource.Factory インスタンス。「 MediaSource.Factory は、プレーヤーの作成時に挿入されます。
  • メディアの個々のコンポーネントをレンダリングする Renderer インスタンス。これらは 挿入されます。
  • MediaSource から提供されたトラックを選択して表示する TrackSelector。 消費します。RendererTrackSelector が注入される プレーヤーが作成されます。
  • MediaSource がより多くのメディアをバッファリングするタイミングを制御する LoadControl。 バッファリングされているメディアの量LoadControl は、プレーヤーがプレーヤーを起動したときに挿入されます。 作成されます。
  • ライブ中の再生速度を制御する LivePlaybackSpeedControl 設定されたライブ オフセットにプレーヤーを近づけることができます。 LivePlaybackSpeedControl は、プレーヤーの作成時に挿入されます。

プレーヤーのパーツを実装するコンポーネントを注入するというコンセプト 機能がライブラリ全体に用意されています。デフォルトの実装では 一部のコンポーネントは、さらに挿入されたコンポーネントに作業を委任します。これにより サブコンポーネントが、それぞれ別の実装に置き換えられる カスタマイズできます。

プレーヤーのカスタマイズ

コンポーネントを挿入してプレーヤーをカスタマイズする一般的な例は、次のとおりです。 以下で説明します。

ネットワーク スタックの構成

ExoPlayer が使用するネットワーク スタックのカスタマイズに関するページがあります。

ネットワークから読み込まれたデータのキャッシュ保存

詳しくは、こちらのガイドをご覧ください。 一時的なオンザフライキャッシュ メディアのダウンロードをご覧ください。

サーバー インタラクションのカスタマイズ

アプリによっては、HTTP リクエストとレスポンスのインターセプトが必要になる場合があります。必要に応じて カスタム リクエスト ヘッダーの挿入、サーバーのレスポンス ヘッダーの読み取り、 リクエストURI などを指定できます。たとえば、アプリは メディア セグメントをリクエストする際のヘッダーとしてのトークン。

次の例は、以下の方法でこれらの動作を実装する方法を示しています。 カスタム DataSource.FactoryDefaultMediaSourceFactory に挿入します。

Kotlin

val dataSourceFactory =
  DataSource.Factory {
    val dataSource = httpDataSourceFactory.createDataSource()
    // Set a custom authentication request header.
    dataSource.setRequestProperty("Header", "Value")
    dataSource
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

DataSource.Factory dataSourceFactory =
    () -> {
      HttpDataSource dataSource = httpDataSourceFactory.createDataSource();
      // Set a custom authentication request header.
      dataSource.setRequestProperty("Header", "Value");
      return dataSource;
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

上記のコード スニペットでは、挿入された HttpDataSource にヘッダーが含まれています。 すべての HTTP リクエストで "Header: Value"。この動作は、すべてのバージョンで修正されています。 やり取りできます。

よりきめ細かいアプローチとして、 ResolvingDataSource。次のコード スニペットは、 HTTP ソースとやり取りする直前に、次のリクエスト ヘッダーを追加します。

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time request headers.
    dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri))
  }

Java

    DataSource.Factory dataSourceFactory =
        new ResolvingDataSource.Factory(
            httpDataSourceFactory,
            // Provide just-in-time request headers.
            dataSpec -> dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)));

また、ResolvingDataSource を使用して、 次のスニペットに示すように、URI のジャストインタイム変更。

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time URI resolution logic.
    dataSpec.withUri(resolveUri(dataSpec.uri))
  }

Java

DataSource.Factory dataSourceFactory =
    new ResolvingDataSource.Factory(
        httpDataSourceFactory,
        // Provide just-in-time URI resolution logic.
        dataSpec -> dataSpec.withUri(resolveUri(dataSpec.uri)));

エラー処理のカスタマイズ

カスタムの LoadErrorHandlingPolicy を実装すると、アプリで ExoPlayer が読み込みエラーに対応します。たとえば、アプリがフェイル ファストを必要とするのは または、バックオフ ロジックをカスタマイズし、 各再試行までのプレーヤーの待機時間を制御します。次のスニペット は、カスタム バックオフ ロジックの実装方法を示しています。

Kotlin

val loadErrorHandlingPolicy: LoadErrorHandlingPolicy =
  object : DefaultLoadErrorHandlingPolicy() {
    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
      // Implement custom back-off logic here.
      return 0
    }
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    )
    .build()

Java

LoadErrorHandlingPolicy loadErrorHandlingPolicy =
    new DefaultLoadErrorHandlingPolicy() {
      @Override
      public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
        // Implement custom back-off logic here.
        return 0;
      }
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy))
        .build();

LoadErrorInfo 引数には、失敗した読み込みに関する詳細情報が含まれます。 エラータイプまたは失敗したリクエストに基づいてロジックをカスタマイズします。

extractor フラグのカスタマイズ

エクストラクタのフラグを使用して、個々の形式の抽出方法をカスタマイズできます。 プログレッシブ メディアです。次の DefaultExtractorsFactory で設定できます。 DefaultMediaSourceFactory に渡されます。次の例では、フラグが MP3 ストリームのインデックス ベースのシークを有効にします。

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING)
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory))
    .build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING);

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

固定ビットレートのシークを有効にする

MP3、ADTS、AMR ストリームでは、 固定ビットレートの前提条件を FLAG_ENABLE_CONSTANT_BITRATE_SEEKING フラグで指定できます。 これらのフラグは、個別の DefaultExtractorsFactory.setXyzExtractorFlags メソッドを使用します。宛先 固定ビットレート シークをサポートするすべてのエクストラクタで有効にするには、 DefaultExtractorsFactory.setConstantBitrateSeekingEnabled

Kotlin

val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);

ExtractorsFactory は、次のように DefaultMediaSourceFactory を介して注入できます。 前に示した extractor フラグのカスタマイズで説明したものです。

非同期バッファ キューイングを有効にする

非同期バッファ キューイングは ExoPlayer のレンダリングの機能強化 MediaCodec インスタンスを非同期モードで操作するパイプライン 追加のスレッドを使用して、データのデコードとレンダリングをスケジュールします。有効にする フレーム落ちやオーディオアンダーランを減らすことができます

Android 12 搭載デバイスでは、非同期バッファ キューイングがデフォルトで有効になっている (API レベル 31)以上が必要です。Android 6.0(API レベル 23)以降では、手動で有効にできます。 接続の切断が観察された特定のデバイスでこの機能を有効にすることを検討してください 特に DRM で保護された、または高フレームレートで再生する場合に、フレームまたはオーディオ アンダーランが発生する 説明します。

最も単純なケースでは、DefaultRenderersFactory をコンテナに注入する必要があります。 使用できます。

Kotlin

val renderersFactory = 
  DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing()
val exoPlayer = ExoPlayer.Builder(context, renderersFactory).build()

Java

DefaultRenderersFactory renderersFactory =
    new DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing();
ExoPlayer exoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();

レンダラを直接インスタンス化する場合は、 AsynchronousMediaCodecAdapter.FactoryMediaCodecVideoRenderer に付与し、 MediaCodecAudioRenderer コンストラクタ。

ForwardingPlayer によるメソッド呼び出しのインターセプト

Player インスタンスをラップすることで、その動作の一部をカスタマイズできます。 ForwardingPlayer のサブクラスを作成し、メソッドをオーバーライドして 次のとおりです。

  • 委譲 Player に渡す前にパラメータにアクセスします。
  • デリゲート Player からの戻り値にアクセスしてから返す。
  • メソッドを完全に再実装します。

ForwardingPlayer メソッドをオーバーライドする場合は、 実装の一貫性を維持し、Player に準拠 特に、API 呼び出しのためのメソッドを 同じまたは関連する動作を検出できます。例:

  • すべての「再生」をオーバーライドする場合は、両方をオーバーライドする必要があります。 ForwardingPlayer.playForwardingPlayer.setPlayWhenReady。これは、 呼び出し元は、これらのメソッドの動作が同じになると playWhenReady = true
  • シーク フォワード インクリメントを変更するには、両方をオーバーライドする必要があります。 ForwardingPlayer.seekForward: カスタマイズされたキーでシークを実行します。 増分、ForwardingPlayer.getSeekForwardIncrement で作成します。 適切なカスタマイズされたインクリメントを呼び出し元に返します。
  • プレーヤーがアドバタイズする Player.Commands を制御する場合 Player.getAvailableCommands()Player.isCommandAvailable() だけでなく、 通知を受け取る Player.Listener.onAvailableCommandsChanged() コールバック 基づくプレーヤーで行われた変更です。

MediaSource のカスタマイズ

上記の例では、すべてのコンポーネントの再生中に使用する、カスタマイズされたコンポーネントを挿入します。 プレーヤーに渡される MediaItem オブジェクト。きめ細かいカスタマイズは カスタマイズしたコンポーネントを個々のシステムに挿入することもできます。 MediaSource インスタンス: プレーヤーに直接渡すことができます。例 以下に、ProgressiveMediaSource をカスタマイズしてカスタム DataSource.FactoryExtractorsFactoryLoadErrorHandlingPolicy:

Kotlin

val mediaSource =
  ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
    .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
    .createMediaSource(MediaItem.fromUri(streamUri))

Java

ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
        .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
        .createMediaSource(MediaItem.fromUri(streamUri));

カスタム コンポーネントを作成する

このライブラリは、上部に一覧表示されているコンポーネントのデフォルト実装を提供します。 一般的なユースケースをご覧ください。ExoPlayer はこれらのコンポーネントを使用できますが、 また、標準以外の動作が確認された場合は、カスタム実装を使用するように作成することもできます。 必要ありません。カスタム実装のユースケースには次のようなものがあります。

  • Renderer – カスタム Renderer を実装して、 デフォルトの実装でサポートされていないメディアタイプです。 ライブラリです。
  • TrackSelector - カスタム TrackSelector を実装すると、アプリが許可されます。 MediaSource によって公開されるトラックの使用方法を変更できる 使用可能な Renderer ごとに消費用に選択されます。
  • LoadControl - カスタム LoadControl を実装すると、アプリが許可されます。 プレーヤーのバッファリング ポリシーを変更することもできます。
  • Extractor – 現在サポートされていないコンテナ形式をサポートする必要がある場合 カスタム Extractor クラスの実装を検討してください。
  • MediaSource – カスタムの MediaSource クラスの実装は、 メディア サンプルを取得してレンダラにフィードしたい場合は、 または、カスタムの MediaSource 合成を実装する場合 確認します。
  • MediaSource.Factory - カスタム MediaSource.Factory を実装する これにより、MediaSource の作成方法をアプリでカスタマイズできます。 MediaItem から。
  • DataSource - ExoPlayer のアップストリーム パッケージには、すでに多数のパッケージが含まれています。 さまざまなユースケースに対応する DataSource の実装。必要に応じて 独自の DataSource クラスを実装して、次のような別の方法でデータを読み込む カスタムのプロトコル、カスタムの HTTP スタックの使用、カスタムの永続ディスクの 作成します。

カスタム コンポーネントを作成する場合は、次のことをおすすめします。

  • カスタム コンポーネントがイベントをアプリに報告する必要がある場合は、 既存の ExoPlayer コンポーネントと同じモデルを使用して行います。 EventDispatcher クラスを使用するか、Handler を引数と一緒に コンポーネントのコンストラクタへのリスナー。
  • カスタム コンポーネントでは、既存の ExoPlayer と同じモデルを使用することをおすすめします。 再生中にアプリが再構成できるようにします。そのためには、 カスタム コンポーネントは、PlayerMessage.Target を実装して handleMessage メソッドでの設定変更アプリケーション コードは、 ExoPlayer の createMessage メソッドを呼び出して構成の変更を渡す メッセージを設定してコンポーネントに PlayerMessage.send。再生スレッドで配信するメッセージを送信する 実行されている他のオペレーションと 順序どおりに実行されるようにします 渡されます。