ЗОЖ

ExoPlayer поддерживает HLS с несколькими форматами контейнеров. Содержащиеся форматы образцов аудио и видео также должны поддерживаться (подробности см. в разделе «Форматы примеров» ). Мы настоятельно рекомендуем производителям контента HLS создавать высококачественные потоки HLS, как описано здесь .

Особенность Поддерживается Комментарии
Контейнеры
MPEG-TS ДА
ФМП4/КМАФ ДА
АДТС (ААС) ДА
МП3 ДА
Скрытые субтитры/субтитры
СЕА-608 ДА
СЕА-708 ДА
ВебВТТ ДА
Метаданные
ID3 ДА
СКТЭ-35 НЕТ
Защита контента
АЭС-128 ДА
Образец АЭС-128 НЕТ
Широкая лоза ДА API 19+ (схема «cenc») и 25+ (схема «cbcs»)
PlayReady SL2000 ДА Только Android-ТВ
Управление сервером
Дельта-обновления ДА
Блокировка перезагрузки плейлиста ДА
Блокировка загрузки подсказок по предварительной загрузке ДА За исключением диапазонов байтов с неопределенной длиной.
Живое воспроизведение
Регулярное живое воспроизведение ДА
HLS с низкой задержкой (Apple) ДА
HLS с низкой задержкой (сообщество) НЕТ
Общие данные медиаклиента (CMCD) ДА Руководство по интеграции

Использование Медиаитем

Чтобы воспроизводить поток HLS, вам необходимо зависеть от модуля HLS.

Котлин

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

классный

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

Затем вы можете создать MediaItem для URI плейлиста HLS и передать его проигрывателю.

Котлин

// 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()

Ява

// 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 в setMimeType MediaItem.Builder чтобы явно указать тип контента.

URI элемента мультимедиа может указывать либо на список воспроизведения мультимедиа, либо на многовариантный список воспроизведения. Если URI указывает на многовариантный список воспроизведения, в котором объявлено несколько тегов #EXT-X-STREAM-INF , то ExoPlayer автоматически адаптируется между вариантами, принимая во внимание как доступную пропускную способность, так и возможности устройства.

Использование HlsMediaSource

Чтобы получить дополнительные возможности настройки, вы можете создать HlsMediaSource и передать его непосредственно проигрывателю вместо MediaItem .

Котлин

// 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()

Ява

// 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 . Обратный вызов onTimelineChanged Player.Listener также вызывается при каждой загрузке манифеста. Это произойдет один раз для контента по запросу и, возможно, много раз для контента в реальном времени. В следующем фрагменте кода показано, как приложение может что-то делать при загрузке манифеста.

Котлин

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.
      }
    }
  }
)

Ява

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 необходимо загрузить медиа-сегмент, чтобы обнаружить эти дополнительные треки, и вместо этого предпочтительно объявить треки со скрытыми субтитрами в многовариантном списке воспроизведения.

Котлин

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

Ява

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

Создание высококачественного HLS-контента

Чтобы получить максимальную отдачу от ExoPlayer, существует ряд рекомендаций, которым вы можете следовать, чтобы улучшить свой HLS-контент. Прочтите нашу публикацию на Medium о воспроизведении HLS в ExoPlayer для получения полного объяснения. Основные моменты:

  • Используйте точную длительность сегментов.
  • Используйте непрерывный медиапоток; избегать изменений в медиаструктуре между сегментами.
  • Используйте тег #EXT-X-INDEPENDENT-SEGMENTS .
  • Отдавайте предпочтение демультиплексированным потокам, а не файлам, содержащим как видео, так и аудио.
  • Включите всю возможную информацию в многовариантный плейлист.

Следующие правила применяются специально для прямых трансляций:

  • Используйте тег #EXT-X-PROGRAM-DATE-TIME .
  • Используйте тег #EXT-X-DISCONTINUITY-SEQUENCE .
  • Обеспечьте окно долгой жизни. Одна минута или больше – это здорово.
,

ExoPlayer поддерживает HLS с несколькими форматами контейнеров. Содержащиеся форматы образцов аудио и видео также должны поддерживаться (подробности см. в разделе «Форматы примеров» ). Мы настоятельно рекомендуем производителям контента HLS создавать высококачественные потоки HLS, как описано здесь .

Особенность Поддерживается Комментарии
Контейнеры
MPEG-TS ДА
ФМП4/КМАФ ДА
АДТС (ААС) ДА
МП3 ДА
Скрытые субтитры/субтитры
СЕА-608 ДА
СЕА-708 ДА
ВебВТТ ДА
Метаданные
ID3 ДА
СКТЭ-35 НЕТ
Защита контента
АЭС-128 ДА
Образец АЭС-128 НЕТ
Широкая лоза ДА API 19+ (схема «cenc») и 25+ (схема «cbcs»)
PlayReady SL2000 ДА Только Android-ТВ
Управление сервером
Дельта-обновления ДА
Блокировка перезагрузки плейлиста ДА
Блокировка загрузки подсказок по предварительной загрузке ДА За исключением диапазонов байтов с неопределенной длиной.
Живое воспроизведение
Регулярное живое воспроизведение ДА
HLS с низкой задержкой (Apple) ДА
HLS с низкой задержкой (сообщество) НЕТ
Общие данные медиаклиента (CMCD) ДА Руководство по интеграции

Использование Медиаитем

Чтобы воспроизводить поток HLS, вам необходимо зависеть от модуля HLS.

Котлин

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

классный

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

Затем вы можете создать MediaItem для URI плейлиста HLS и передать его проигрывателю.

Котлин

// 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()

Ява

// 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 в setMimeType MediaItem.Builder чтобы явно указать тип контента.

URI элемента мультимедиа может указывать либо на список воспроизведения мультимедиа, либо на многовариантный список воспроизведения. Если URI указывает на многовариантный список воспроизведения, в котором объявлено несколько тегов #EXT-X-STREAM-INF , то ExoPlayer автоматически адаптируется между вариантами, принимая во внимание как доступную пропускную способность, так и возможности устройства.

Использование HlsMediaSource

Для получения дополнительных возможностей настройки вы можете создать HlsMediaSource и передать его непосредственно проигрывателю вместо MediaItem .

Котлин

// 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()

Ява

// 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 . Обратный вызов onTimelineChanged Player.Listener также вызывается при каждой загрузке манифеста. Это произойдет один раз для контента по запросу и, возможно, много раз для живого контента. В следующем фрагменте кода показано, как приложение может что-то делать при загрузке манифеста.

Котлин

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.
      }
    }
  }
)

Ява

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 необходимо загрузить медиа-сегмент, чтобы обнаружить эти дополнительные треки, и вместо этого предпочтительно объявить треки со скрытыми субтитрами в многовариантном списке воспроизведения.

Котлин

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

Ява

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

Создание высококачественного HLS-контента

Чтобы получить максимальную отдачу от ExoPlayer, существует ряд рекомендаций, которым вы можете следовать, чтобы улучшить свой HLS-контент. Прочтите нашу публикацию на Medium о воспроизведении HLS в ExoPlayer для получения полного объяснения. Основные моменты:

  • Используйте точную длительность сегментов.
  • Используйте непрерывный медиапоток; избегать изменений в медиаструктуре между сегментами.
  • Используйте тег #EXT-X-INDEPENDENT-SEGMENTS .
  • Отдавайте предпочтение демультиплексированным потокам, а не файлам, содержащим как видео, так и аудио.
  • Включите всю возможную информацию в многовариантный плейлист.

Следующие правила применяются специально для прямых трансляций:

  • Используйте тег #EXT-X-PROGRAM-DATE-TIME .
  • Используйте тег #EXT-X-DISCONTINUITY-SEQUENCE .
  • Обеспечьте окно долгой жизни. Одна минута или больше – это здорово.