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(社区版)
通用媒体客户端数据 (CMCD) 集成指南

使用 MediaItem

如需播放 HLS 直播,您需要依赖于 HLS 模块。

Kotlin

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

Groovy

implementation "androidx.media3:media3-exoplayer-hls:1.4.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_M3U8 传递给 MediaItem.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 回调。对于点播内容,系统会执行一次此操作;对于直播内容,系统可能会执行多次此操作。以下代码段展示了应用如何在每次加载清单时执行操作。

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 内容。如需了解完整说明,请参阅我们的 Medium 博文(关于 ExoPlayer 中的 HLS 播放)。主要要点如下:

  • 使用精确的片段时长。
  • 使用连续的媒体流;避免在各个片段中更改媒体结构。
  • 使用 #EXT-X-INDEPENDENT-SEGMENTS 标记。
  • 首选解复 mux 的串流,而不是同时包含视频和音频的文件。
  • 在多变体商品目录中添加尽可能多的信息。

以下指南专门适用于直播:

  • 使用 #EXT-X-PROGRAM-DATE-TIME 标记。
  • 使用 #EXT-X-DISCONTINUITY-SEQUENCE 标记。
  • 提供较长的直播时长。一分钟或更长时间就很棒了。