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 のみ | 
| サーバー制御 | ||
| 差分更新 | ○ | |
| 再生リストの再読み込みをブロック | ○ | |
| プリロード ヒントの読み込みをブロック | ○ | 長さが未定義のバイト範囲を除く | 
| 広告挿入 | ||
| サーバーガイド付き広告挿入 (インタースティシャル) | 部分的 | X-ASSET-URIの VOD のみ。ライブ配信とX-ASSET-LISTは後日追加されます。 | 
| IMA サーバーサイド広告とクライアントサイド広告 | ○ | 広告挿入ガイド | 
| ライブ再生 | ||
| 通常のライブ再生 | ○ | |
| 低遅延 HLS(Apple) | ○ | |
| 低レイテンシ HLS(コミュニティ) | いいえ | |
| 共通メディア クライアント データ CMCD | ○ | CMCD 統合ガイド | 
MediaItem の使用
HLS ストリームを再生するには、HLS モジュールに依存する必要があります。
Kotlin
implementation("androidx.media3:media3-exoplayer-hls:1.8.0")
Groovy
implementation "androidx.media3:media3-exoplayer-hls:1.8.0"
次に、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 で終わらない場合は、MediaItem.Builder の setMimeType に MimeTypes.APPLICATION_M3U8 を渡して、コンテンツのタイプを明示的に示すことができます。
メディア アイテムの URI は、メディア プレイリストまたはマルチバリアント プレイリストのいずれかを指す場合があります。URI が複数の #EXT-X-STREAM-INF タグを宣言するマルチバリアント プレイリストを指している場合、ExoPlayer は利用可能な帯域幅とデバイスの性能の両方を考慮して、バリアント間で自動的に適応します。
HlsMediaSource を使用する
カスタマイズ オプションをさらに追加するには、MediaItem の代わりに HlsMediaSource を作成してプレーヤーに直接渡します。
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.Listener の onTimelineChanged コールバックも呼び出されます。オンデマンド コンテンツの場合は 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.
        }
      }
    });
インタースティシャルを含む HLS ストリームを再生する
HLS 仕様では、メディア プレイリストにインタースティシャル情報を含めるために使用できる HLS インタースティシャルが定義されています。ExoPlayer はデフォルトでこれらのインタースティシャルを無視します。サポートは HlsInterstitialsAdsLoader を使用して追加できます。仕様のすべての機能が最初からサポートされるわけではありません。ストリームのサポートが不足している場合は、GitHub で問題を報告し、ストリーム URI をお送りください。ストリームのサポートを追加いたします。
プレイリスト API で MediaItem を使用する
インタースティシャルを含む HLS ストリームを再生する最も便利な方法は、HlsInterstitialsAdsLoader.AdsMediaSourceFactory を使用して ExoPlayer インスタンスをビルドすることです。これにより、Player インターフェースの MediaItem ベースのプレイリスト API を使用して HLS インタースティシャルを再生できます。
プレーヤー インスタンスのビルド時に、ExoPlayer の MediaSource.Factory をビルダーに挿入できます。
Kotlin
hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context)
// Create a MediaSource.Factory for HLS streams with interstitials.
val hlsMediaSourceFactory =
  HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
    hlsInterstitialsAdsLoader,
    playerView,
    DefaultMediaSourceFactory(context),
  )
// Build player with interstitials media source factory
player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(hlsMediaSourceFactory)
    .build()
// Set the player on the ads loader.
hlsInterstitialsAdsLoader.setPlayer(player)
playerView.setPlayer(player)
Java
hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(context);
// Create a MediaSource.Factory for HLS streams with interstitials.
MediaSource.Factory hlsMediaSourceFactory =
      new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
          hlsInterstitialsAdsLoader, playerView, new DefaultMediaSourceFactory(context));
// Build player with interstitials media source factory
player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(hlsMediaSourceFactory)
        .build();
// Set the player on the ads loader.
hlsInterstitialsAdsLoader.setPlayer(player);
playerView.setPlayer(player);
このようなプレーヤーの設定では、HLS インタースティシャルを再生するには、プレーヤーで AdsConfiguration を使用してメディア アイテムを設定するだけです。
Kotlin
player.setMediaItem(
  MediaItem.Builder()
    .setUri("https://www.example.com/media.m3u8")
    .setAdsConfiguration(
      MediaItem.AdsConfiguration.Builder("hls://interstitials".toUri())
        .setAdsId("ad-tag-0") // must be unique within playlist
        .build())
    .build())
player.prepare()
player.play()
Java
player.setMediaItem(
    new MediaItem.Builder()
        .setUri("https://www.example.com/media.m3u8")
        .setAdsConfiguration(
            new AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
                .setAdsId("ad-tag-0") // must be unique within playlist
                .build())
        .build());
player.prepare();
player.play();
メディアソース ベースの API を使用する
または、デフォルトのメディアソース ファクトリをオーバーライドせずに ExoPlayer インスタンスをビルドすることもできます。インタースティシャルをサポートするために、アプリは HlsInterstitialsAdsLoader.AdsMediaSourceFactory を直接使用して MediaSource を作成し、メディアソース ベースのプレイリスト API を使用して ExoPlayer に提供できます。
Kotlin
hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context)
// Create a MediaSource.Factory for HLS streams with interstitials.
val hlsMediaSourceFactory =
  HlsInterstitialsAdsLoader.AdsMediaSourceFactory(hlsInterstitialsAdsLoader, playerView, context)
// Build player with default media source factory.
player = ExoPlayer.Builder(context).build();
// Create an media source from an HLS media item with ads configuration.
val mediaSource =
  hlsMediaSourceFactory.createMediaSource(
    MediaItem.Builder()
      .setUri("https://www.example.com/media.m3u8")
      .setAdsConfiguration(
        MediaItem.AdsConfiguration.Builder("hls://interstitials".toUri())
          .setAdsId("ad-tag-0")
          .build()
      )
      .build()
  )
// Set the media source on the player.
player.setMediaSource(mediaSource)
player.prepare()
player.play()
Java
HlsInterstitialsAdsLoader hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(context);
// Create a MediaSource.Factory for HLS streams with interstitials.
MediaSource.Factory hlsMediaSourceFactory =
    new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
      hlsInterstitialsAdsLoader, playerView, context);
// Build player with default media source factory.
player = new ExoPlayer.Builder(context).build();
// Create an media source from an HLS media item with ads configuration.
MediaSource mediaSource =
    hlsMediaSourceFactory.createMediaSource(
      new MediaItem.Builder()
        .setUri("https://www.example.com/media.m3u8")
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
                .setAdsId("ad-tag-0")
                .build())
        .build());
// Set the media source on the player.
exoPlayer.setMediaSource(mediaSource);
exoPlayer.prepare();
exoPlayer.play();
広告イベントをリッスンする
Listener を HlsInterstitialsAdsLoader に追加して、HLS インタースティシャル再生に関するステータス変更のイベントをモニタリングできます。これにより、アプリや SDK は、再生された広告、読み込まれているアセット リスト、準備中の広告メディア ソースをトラッキングしたり、アセット リストの読み込みエラーや広告の準備エラーを検出したりできます。また、広告メディア ソースから出力されたメタデータを受信して、広告再生のきめ細かい検証や広告再生の進行状況のトラッキングを行うことができます。
Kotlin
class AdsLoaderListener : HlsInterstitialsAdsLoader.Listener {
  override fun onStart(mediaItem: MediaItem, adsId: Any, adViewProvider: AdViewProvider) {
    // Do something when HLS media item with interstitials is started.
  }
  override fun onMetadata(
    mediaItem: MediaItem,
    adsId: Any,
    adGroupIndex: Int,
    adIndexInAdGroup: Int,
    metadata: Metadata,
  ) {
    // Do something with metadata that is emitted by the ad media source of the given ad.
  }
  override fun onAdCompleted(
    mediaItem: MediaItem,
    adsId: Any,
    adGroupIndex: Int,
    adIndexInAdGroup: Int,
  ) {
    // Do something when ad completed playback.
  }
  // ... See JavaDoc for further callbacks of HlsInterstitialsAdsLoader.Listener.
  override fun onStop(mediaItem: MediaItem, adsId: Any, adPlaybackState: AdPlaybackState) {
    // Do something with the resulting ad playback state when stopped.
  }
}
Java
private class AdsLoaderListener
    implements HlsInterstitialsAdsLoader.Listener {
  // implement HlsInterstitialsAdsLoader.Listener
  @Override
  public void onStart(MediaItem mediaItem, Object adsId, AdViewProvider adViewProvider) {
    // Do something when HLS media item with interstitials is started.
  }
  @Override
  public void onMetadata(
      MediaItem mediaItem,
      Object adsId,
      int adGroupIndex,
      int adIndexInAdGroup,
      Metadata metadata) {
    // Do something with metadata that is emitted by the ad media source of the given ad.
  }
  @Override
  public void onAdCompleted(
      MediaItem mediaItem, Object adsId, int adGroupIndex, int adIndexInAdGroup) {
    // Do something when ad completed playback.
  }
  // ... See JavaDoc for further callbacks
  @Override
  public void onStop(MediaItem mediaItem, Object adsId, AdPlaybackState adPlaybackState) {
    // Do something with the resulting ad playback state when stopped.
  }
}
使用可能なすべてのコールバックの詳細なドキュメントについては、HlsInterstitialsAdsLoader.Listener の JavaDoc をご覧ください。
リスナーを広告ローダーに追加できます。
Kotlin
val listener  = AdsLoaderListener()
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener)
Java
AdsLoaderListener listener = new AdsLoaderListener();
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener);
HlsInterstitialsAdsLoader ライフサイクル
HlsInterstitialsAdsLoader または HlsInterstitialsAdsLoader.AdsMediaSourceFactory のインスタンスは、広告を読み込む必要がある複数のメディアソースを作成する複数のプレーヤー インスタンスで再利用できます。
たとえば、Activity の onCreate メソッドでインスタンスを作成し、複数のプレーヤー インスタンスで再利用できます。これは、同時に 1 つのプレーヤー インスタンスで使用されている場合に機能します。これは、アプリがバックグラウンドに移行し、プレーヤー インスタンスが破棄されてから、アプリが再びフォアグラウンドに移行したときに新しいインスタンスが作成されるという一般的なユースケースで役立ちます。
広告の再生状態を使用した再生の再開
ユーザーが広告を再度視聴する必要がないように、プレーヤーが再作成されたときに広告の再生状態を保存して復元できます。これを行うには、プレーヤーがリリースされようとしているときに getAdsResumptionStates() を呼び出し、返された AdsResumptionState オブジェクトを保存します。プレーヤーが再作成されると、広告ローダー インスタンスで addAdResumptionState() を呼び出すことで状態を復元できます。AdsResumptionState はバンドル可能であるため、Activity の onSaveInstanceState バンドルに保存できます。広告の再開は VOD ストリームでのみサポートされています。
Kotlin
companion object {
  const val ADS_RESUMPTION_STATE_KEY = "ads_resumption_state"
}
private var hlsInterstitialsAdsLoader: HlsInterstitialsAdsLoader? = null
private var playerView: PlayerView? = null
private var player: ExoPlayer? = null
private var adsResumptionStates: List<HlsInterstitialsAdsLoader.AdsResumptionState>? = null
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // Create the ads loader instance.
  hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(this)
  // Restore ad resumption states.
  savedInstanceState?.getParcelableArrayList<Bundle>(ADS_RESUMPTION_STATE_KEY)?.let { bundles ->
    adsResumptionStates =
      bundles.map { HlsInterstitialsAdsLoader.AdsResumptionState.fromBundle(it) }
  }
}
override fun onStart() {
  super.onStart()
  // Build a player and set it on the ads loader.
  initializePlayer()
  hlsInterstitialsAdsLoader?.setPlayer(player)
  // Add any stored ad resumption states to the ads loader.
  adsResumptionStates?.forEach { hlsInterstitialsAdsLoader?.addAdResumptionState(it) }
  adsResumptionStates = null // Consume the states
}
override fun onStop() {
  super.onStop()
  // Get ad resumption states.
  adsResumptionStates = hlsInterstitialsAdsLoader?.adsResumptionStates
  releasePlayer()
}
override fun onDestroy() {
  // Release the ads loader when not used anymore.
  hlsInterstitialsAdsLoader?.release()
  hlsInterstitialsAdsLoader = null
  super.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
  super.onSaveInstanceState(outState)
  // Store the ad resumption states.
  adsResumptionStates?.let {
    outState.putParcelableArrayList(
      ADS_RESUMPTION_STATE_KEY,
      ArrayList(it.map(HlsInterstitialsAdsLoader.AdsResumptionState::toBundle)),
    )
  }
}
fun initializePlayer() {
  if (player == null) {
    // Create a media source factory for HLS streams.
    val hlsMediaSourceFactory =
      HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
        checkNotNull(hlsInterstitialsAdsLoader),
        playerView!!,
        /* context= */ this,
      )
    // Build player with interstitials media source
    player =
      ExoPlayer.Builder(/* context= */ this).setMediaSourceFactory(hlsMediaSourceFactory).build()
    // Set the player on the ads loader.
    hlsInterstitialsAdsLoader?.setPlayer(player)
    playerView?.player = player
  }
  // Use a media item with an HLS stream URI, an ad tag URI and ads ID.
  player?.setMediaItem(
    MediaItem.Builder()
      .setUri("https://www.example.com/media.m3u8")
      .setMimeType(MimeTypes.APPLICATION_M3U8)
      .setAdsConfiguration(
        MediaItem.AdsConfiguration.Builder("hls://interstitials".toUri())
          .setAdsId("ad-tag-0") // must be unique within ExoPlayer playlist
          .build()
      )
      .build()
  )
  player?.prepare()
  player?.play()
}
fun releasePlayer() {
  player?.release()
  player = null
  hlsInterstitialsAdsLoader?.setPlayer(null)
  playerView?.setPlayer(null)
}
Java
public static final String ADS_RESUMPTION_STATE_KEY = "ads_resumption_state";
@Nullable private HlsInterstitialsAdsLoader hlsInterstitialsAdsLoader;
@Nullable private PlayerView playerView;
@Nullable private ExoPlayer player;
private List<HlsInterstitialsAdsLoader.AdsResumptionState> adsResumptionStates;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // Create the ads loader instance.
  hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(this);
  // Restore ad resumption states.
  if (savedInstanceState != null) {
    ArrayList<Bundle> bundles =
        savedInstanceState.getParcelableArrayList(ADS_RESUMPTION_STATE_KEY);
    if (bundles != null) {
      adsResumptionStates = new ArrayList<>();
      for (Bundle bundle : bundles) {
        adsResumptionStates.add(
            HlsInterstitialsAdsLoader.AdsResumptionState.fromBundle(bundle));
      }
    }
  }
}
@Override
protected void onStart() {
  super.onStart();
  // Build a player and set it on the ads loader.
  initializePlayer();
  // Add any stored ad resumption states to the ads loader.
  if (adsResumptionStates != null) {
    for (HlsInterstitialsAdsLoader.AdsResumptionState state : adsResumptionStates) {
      hlsInterstitialsAdsLoader.addAdResumptionState(state);
    }
    adsResumptionStates = null; // Consume the states
  }
}
@Override
protected void onStop() {
  super.onStop();
  // Get ad resumption states before releasing the player.
  adsResumptionStates = hlsInterstitialsAdsLoader.getAdsResumptionStates();
  releasePlayer();
}
@Override
protected void onDestroy() {
  // Release the ads loader when not used anymore.
  if (hlsInterstitialsAdsLoader != null) {
    hlsInterstitialsAdsLoader.release();
    hlsInterstitialsAdsLoader = null;
  }
  super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  // Store the ad resumption states.
  if (adsResumptionStates != null) {
    ArrayList<Bundle> bundles = new ArrayList<>();
    for (HlsInterstitialsAdsLoader.AdsResumptionState state : adsResumptionStates) {
      bundles.add(state.toBundle());
    }
    outState.putParcelableArrayList(ADS_RESUMPTION_STATE_KEY, bundles);
  }
}
private void initializePlayer() {
  if (player == null) {
    // Create a media source factory for HLS streams.
    MediaSource.Factory hlsMediaSourceFactory =
        new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
            checkNotNull(hlsInterstitialsAdsLoader), playerView, /* context= */ this);
    // Build player with interstitials media source
    player =
        new ExoPlayer.Builder(/* context= */ this)
            .setMediaSourceFactory(hlsMediaSourceFactory)
            .build();
    // Set the player on the ads loader.
    hlsInterstitialsAdsLoader.setPlayer(player);
    playerView.setPlayer(player);
  }
  // Use a media item with an HLS stream URI, an ad tag URI and ads ID.
  player.setMediaItem(
      new MediaItem.Builder()
          .setUri("https://www.example.com/media.m3u8")
          .setMimeType(MimeTypes.APPLICATION_M3U8)
          .setAdsConfiguration(
              new MediaItem.AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
                  .setAdsId("ad-tag-0") // must be unique within ExoPlayer playlist
                  .build())
          .build());
  player.prepare();
  player.play();
}
private void releasePlayer() {
  if (player != null) {
    player.release();
    player = null;
  }
  if (hlsInterstitialsAdsLoader != null) {
    hlsInterstitialsAdsLoader.setPlayer(null);
  }
  if (playerView != null) {
    playerView.setPlayer(null);
  }
}
removeAdResumptionState(Object adsId) を使用して個々の再開状態を削除したり、clearAllAdResumptionStates() を使用してすべてをクリアしたりすることもできます。
一般に、広告ローダーに次のプレーヤー インスタンスを設定する前に、古いプレーヤー インスタンスを解放してください。広告ローダー自体がリリースされると、広告ローダーは使用できなくなります。
再生をカスタマイズする
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 分以上が理想です。
