Прямая трансляция

ExoPlayer воспроизводит большинство адаптивных прямых трансляций «из коробки» без какой-либо специальной настройки. Дополнительную информацию см. на странице «Поддерживаемые форматы» .

Адаптивные прямые трансляции предлагают окно доступных медиафайлов, которое регулярно обновляется в соответствии с текущим режимом реального времени. Это означает, что позиция воспроизведения всегда будет где-то в этом окне, в большинстве случаев близка к текущему реальному времени, в котором создается поток. Разница между текущим положением реального времени и позицией воспроизведения называется живым смещением .

Обнаружение и мониторинг воспроизведения в реальном времени

Каждый раз, когда обновляется окно реального времени, зарегистрированные экземпляры Player.Listener получат событие onTimelineChanged . Вы можете получить подробную информацию о текущем воспроизведении в реальном времени, запросив различные методы Player и Timeline.Window , как указано ниже и показано на следующем рисунке.

Живое окно

  • Player.isCurrentWindowLive указывает, является ли воспроизводимый в данный момент элемент мультимедиа прямым потоком. Это значение по-прежнему актуально, даже если прямая трансляция завершилась.
  • Player.isCurrentWindowDynamic указывает, обновляется ли воспроизводимый в данный момент элемент мультимедиа. Обычно это справедливо для прямых трансляций, которые еще не закончились. Обратите внимание, что в некоторых случаях этот флаг также верен и для непрямых потоков.
  • Player.getCurrentLiveOffset возвращает смещение между текущим реальным временем и позицией воспроизведения (если доступно).
  • Player.getDuration возвращает длину текущего окна прямой трансляции.
  • Player.getCurrentPosition возвращает позицию воспроизведения относительно начала окна прямой трансляции.
  • Player.getCurrentMediaItem возвращает текущий элемент мультимедиа, где MediaItem.liveConfiguration содержит предоставленные приложением переопределения для целевого смещения в реальном времени и параметров регулировки смещения в реальном времени.
  • Player.getCurrentTimeline возвращает текущую структуру мультимедиа на Timeline . Текущий Timeline.Window можно получить из Timeline с помощью Player.getCurrentMediaItemIndex и Timeline.getWindow . В Window :
    • Window.liveConfiguration содержит целевое смещение в реальном времени и параметры регулировки смещения в реальном времени. Эти значения основаны на информации на носителе и любых переопределениях, предоставленных приложением, заданных в MediaItem.liveConfiguration .
    • Window.windowStartTimeMs — это время, начиная с эпохи Unix, когда запускается живое окно.
    • Window.getCurrentUnixTimeMs — это время, прошедшее с начала эпохи Unix текущего реального времени. Это значение может быть скорректировано известной разницей часов между сервером и клиентом.
    • Window.getDefaultPositionMs — это позиция в окне реального времени, с которой проигрыватель начнет воспроизведение по умолчанию.

Ищу в прямых трансляциях

Вы можете перейти в любое место в окне реального времени, используя Player.seekTo . Передаваемая позиция поиска относится к началу окна реального времени. Например, seekTo(0) будет искать начало окна реального времени. После поиска игрок попытается сохранить то же живое смещение, что и искомая позиция.

Окно живого видео также имеет позицию по умолчанию, с которой должно начинаться воспроизведение. Эта позиция обычно находится где-то рядом с живым преимуществом. Вы можете перейти к позиции по умолчанию, вызвав Player.seekToDefaultPosition .

Пользовательский интерфейс воспроизведения в реальном времени

Компоненты пользовательского интерфейса ExoPlayer по умолчанию показывают продолжительность окна реального времени и текущую позицию воспроизведения в нем. Это означает, что позиция будет перемещаться назад каждый раз при обновлении окна реального времени. Если вам нужно другое поведение, например, отображение времени Unix или текущего смещения в реальном времени, вы можете разветвить PlayerControlView и изменить его в соответствии со своими потребностями.

Настройка параметров живого воспроизведения

ExoPlayer использует некоторые параметры для управления смещением позиции воспроизведения от живого края и диапазоном скоростей воспроизведения, которые можно использовать для регулировки этого смещения.

ExoPlayer получает значения этих параметров из трёх мест, в порядке убывания приоритета (используется первое найденное значение):

  • Значения MediaItem , передаваемые в MediaItem.Builder.setLiveConfiguration .
  • Глобальные значения по умолчанию, установленные в DefaultMediaSourceFactory .
  • Ценности считываются непосредственно из средств массовой информации.

Котлин

// Global settings.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
    .build()

// Per MediaItem settings.
val mediaItem =
  MediaItem.Builder()
    .setUri(mediaUri)
    .setLiveConfiguration(
      MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()
    )
    .build()
player.setMediaItem(mediaItem)

Ява

// Global settings.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
        .build();

// Per MediaItem settings.
MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(mediaUri)
        .setLiveConfiguration(
            new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build())
        .build();
player.setMediaItem(mediaItem);

Доступные значения конфигурации:

  • targetOffsetMs : целевое смещение в реальном времени. Если это возможно, проигрыватель попытается приблизиться к этому реальному смещению во время воспроизведения.
  • minOffsetMs : минимально допустимое смещение в реальном времени. Даже при настройке смещения в соответствии с текущими условиями сети проигрыватель не будет пытаться снизить это смещение во время воспроизведения.
  • maxOffsetMs : максимально допустимое смещение в реальном времени. Даже при настройке смещения в соответствии с текущими условиями сети проигрыватель не будет пытаться превысить это смещение во время воспроизведения.
  • minPlaybackSpeed : минимальная скорость воспроизведения, которую проигрыватель может использовать для возврата при попытке достичь целевого смещения в реальном времени.
  • maxPlaybackSpeed : максимальная скорость воспроизведения, которую плеер может использовать, чтобы наверстать упущенное при попытке достичь целевого смещения в реальном времени.

Регулировка скорости воспроизведения

При воспроизведении прямого потока с малой задержкой ExoPlayer регулирует смещение в реальном времени, слегка изменяя скорость воспроизведения. Плеер попытается соответствовать целевому смещению в реальном времени, предоставленному мультимедиа или приложением, но также попытается отреагировать на изменение условий сети. Например, если во время воспроизведения возникают ребуферы, проигрыватель немного замедлит воспроизведение, чтобы отойти дальше от живого края. Если сеть затем станет достаточно стабильной, чтобы снова поддерживать воспроизведение ближе к реальному краю, проигрыватель ускорит воспроизведение, чтобы вернуться к целевому смещению в реальном времени.

Если автоматическая регулировка скорости воспроизведения нежелательна, ее можно отключить, установив для свойств minPlaybackSpeed ​​и maxPlaybackSpeed ​​значение 1.0f . Аналогично, его можно включить для прямых трансляций с не низкой задержкой, явно установив для них значения, отличные от 1.0f . Дополнительную информацию о том, как можно установить эти свойства, см. в разделе конфигурации выше.

Настройка алгоритма регулировки скорости воспроизведения

Если регулировка скорости включена, LivePlaybackSpeedControl определяет, какие корректировки выполняются. Можно реализовать собственный LivePlaybackSpeedControl или настроить реализацию по умолчанию, то есть DefaultLivePlaybackSpeedControl . В обоих случаях экземпляр можно установить при сборке плеера:

Котлин

val player =
  ExoPlayer.Builder(context)
    .setLivePlaybackSpeedControl(
      DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build()
    )
    .build()

Ява

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setLivePlaybackSpeedControl(
            new DefaultLivePlaybackSpeedControl.Builder()
                .setFallbackMaxPlaybackSpeed(1.04f)
                .build())
        .build();

Соответствующие параметры настройки DefaultLivePlaybackSpeedControl :

  • fallbackMinPlaybackSpeed ​​и fallbackMaxPlaybackSpeed : минимальная и максимальная скорости воспроизведения, которые можно использовать для настройки, если ни носитель, ни предоставленный приложением MediaItem не определяют ограничения.
  • proportionalControlFactor : контролирует плавность регулировки скорости. Высокое значение делает корректировки более внезапными и реактивными, но при этом делает их более слышимыми. Меньшее значение приводит к более плавному переходу между скоростями за счет замедления.
  • targetLiveOffsetIncrementOnRebufferMs : это значение добавляется к целевому реальному смещению всякий раз, когда происходит повторная буферизация, чтобы действовать более осторожно. Эту функцию можно отключить, установив значение 0.
  • minPossibleLiveOffsetSmoothingFactor : коэффициент экспоненциального сглаживания, который используется для отслеживания минимально возможного смещения в реальном времени на основе текущего буферизованного мультимедиа. Значение, очень близкое к 1, означает, что оценка является более осторожной и может потребоваться больше времени для адаптации к улучшенным условиям сети, тогда как более низкое значение означает, что оценка будет корректироваться быстрее с более высоким риском столкнуться с ребуферами.

BehindLiveWindowException и ERROR_CODE_BEHIND_LIVE_WINDOW

Позиция воспроизведения может отставать от окна реального времени, например, если проигрыватель поставлен на паузу или находится в буферизации в течение достаточно длительного периода времени. Если это произойдет, воспроизведение завершится неудачно, и через Player.Listener.onPlayerError будет сообщено об исключении с кодом ошибки ERROR_CODE_BEHIND_LIVE_WINDOW . Код приложения может захотеть обработать такие ошибки, возобновив воспроизведение с позиции по умолчанию. PlayerActivity демонстрационного приложения иллюстрирует этот подход.

Котлин

override fun onPlayerError(error: PlaybackException) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition()
    player.prepare()
  } else {
    // Handle other errors
  }
}

Ява

@Override
public void onPlayerError(PlaybackException error) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition();
    player.prepare();
  } else {
    // Handle other errors
  }
}