HLS

ExoPlayer は、複数のコンテナ形式で HLS をサポートしています。含まれる音声と動画のサンプル形式もサポートしている必要があります(詳細については、サンプル形式をご覧ください)。こちらで説明されているように、HLS コンテンツ プロデューサーには高品質の HLS ストリームを生成することを強くおすすめします。

機能 対応 コメント
コンテナ
MPEG-TS はい
FMP4/CMAF はい
ADTS(AAC) はい
MP3 はい
字幕
CEA-608 はい
CEA-708 はい
WebVTT はい
メタデータ
ID3 はい
SCTE-35 ×
コンテンツの保護
AES-128 はい
サンプル AES-128 ×
Widevine はい API 19 以降(「cenc」スキーム)と 25 以降(「cbcs」スキーム)
PlayReady SL2000 はい Android TV のみ
サーバー コントロール
差分更新 はい
再生リストの再読み込みをブロックしています はい
プリロード ヒントのロードのブロック はい 長さが未定義のバイト範囲を除く
ライブ再生
通常のライブ再生 はい
低遅延 HLS(Apple) はい
低レイテンシ HLS(コミュニティ) ×
Common Media Client Data(CMCD) はい 統合ガイド

MediaItem の使用

HLS ストリームを再生するには、HLS モジュールに依存する必要があります。

Kotlin

implementation("androidx.media3:media3-exoplayer-hls:1.3.1")

Groovy

implementation "androidx.media3:media3-exoplayer-hls:1.3.1"

次に、HLS 再生リスト URI の MediaItem を作成してプレーヤーに渡すことができます。

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri))
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri));
// Prepare the player.
player.prepare();

URI の末尾が .m3u8 ではない場合は、MimeTypes.APPLICATION_M3U8MediaItem.BuildersetMimeType に渡して、コンテンツのタイプを明示的に示すことができます。

メディア アイテムの URI は、メディア再生リストまたはマルチバリエーション再生リストのいずれかを指します。URI が、複数の #EXT-X-STREAM-INF タグを宣言するマルチバリアント再生リストをポイントしている場合、ExoPlayer は利用可能な帯域幅とデバイス機能の両方を考慮して、バリアント間で自動的に適応します。

HlsMediaSource の使用

他のカスタマイズ オプションが必要な場合は、HlsMediaSource を作成し、MediaItem ではなくプレーヤーに直接渡すことができます。

Kotlin

// Create a data source factory.
val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory()
// Create a HLS media source pointing to a playlist uri.
val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri))
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri));
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource);
// Prepare the player.
player.prepare();

マニフェストへのアクセス

現在のマニフェストを取得するには、Player.getCurrentManifest を呼び出します。HLS の場合、返されたオブジェクトを HlsManifest にキャストする必要があります。また、マニフェストが読み込まれるたびに、Player.ListeneronTimelineChanged コールバックが呼び出されます。この処理はオンデマンド コンテンツで 1 回、ライブ コンテンツで複数回行われます。次のコード スニペットは、マニフェストが読み込まれたときにアプリがなんらかの操作を行う方法を示しています。

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
      val manifest = player.currentManifest
      if (manifest is HlsManifest) {
        // Do something with the manifest.
      }
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTimelineChanged(
          Timeline timeline, @Player.TimelineChangeReason int reason) {
        Object manifest = player.getCurrentManifest();
        if (manifest != null) {
          HlsManifest hlsManifest = (HlsManifest) manifest;
          // Do something with the manifest.
        }
      }
    });

再生のカスタマイズ

ExoPlayer には、アプリのニーズに合わせて再生エクスペリエンスを調整する方法が複数用意されています。例については、カスタマイズのページをご覧ください。

チャンクレス準備の無効化

デフォルトでは、ExoPlayer はチャンクレス準備を使用します。つまり、ExoPlayer はマルチバリエーション再生リストの情報のみを使用してストリームを準備します。これは、#EXT-X-STREAM-INF タグに CODECS 属性が含まれている場合に機能します。

#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS タグを使用してマルチバリエーション再生リストで宣言されていない多重化された字幕トラックがメディア セグメントに含まれている場合は、この機能を無効にする必要があります。そうしないと、字幕トラックは検出されず、再生されません。次のスニペットに示すように、HlsMediaSource.Factory でチャンクレス準備を無効にできます。ただし、ExoPlayer は追加のトラックを検出するためにメディア セグメントをダウンロードする必要があるため、起動時間が長くなります。マルチバリエーション再生リストで字幕トラックを宣言することをおすすめします。

Kotlin

val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory)
    .setAllowChunklessPreparation(false)
    .createMediaSource(MediaItem.fromUri(hlsUri))

Java

HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory)
        .setAllowChunklessPreparation(false)
        .createMediaSource(MediaItem.fromUri(hlsUri));

高品質な HLS コンテンツの作成

ExoPlayer を最大限に活用するため、HLS コンテンツを改善するためのガイドラインがいくつかあります。詳しくは、ExoPlayer での HLS 再生に関する Medium の投稿をご覧ください。主なポイントは次のとおりです。

  • 正確なセグメントの長さを使用します。
  • 連続したメディア ストリームを使用します。セグメント間でメディア構造を変更しないでください。
  • #EXT-X-INDEPENDENT-SEGMENTS タグを使用します。
  • 動画と音声の両方を含むファイルではなく、分離ストリームを優先します。
  • マルチバリエーション再生リストにできるだけ多くの情報を含めます。

以下のガイドラインは特にライブ配信に適用されます。

  • #EXT-X-PROGRAM-DATE-TIME タグを使用します。
  • #EXT-X-DISCONTINUITY-SEQUENCE タグを使用します。
  • 有効期間を長くします。1 分以上であれば問題ありません。