ExoPlayer воспроизводит большинство адаптивных прямых трансляций без каких-либо специальных настроек. Подробную информацию можно найти на странице Поддерживаемые форматы.
Адаптивные трансляции предлагают окно доступных медиа, которое обновляется через регулярные интервалы, чтобы соответствовать текущему моменту в реальном времени. Это означает, что позиция воспроизведения всегда будет находиться где-то в этом окне, в большинстве случаев близко к текущему реальному времени, в котором создается поток. Разница между текущим временем в реальном времени и позицией воспроизведения называется смещением трансляции.
Как выявлять и отслеживать воспроизведения в прямом эфире
Каждый раз, когда обновляется окно прямого эфира, зарегистрированные экземпляры Player.Listener получают событие onTimelineChanged. Вы можете получить информацию о текущем воспроизведении трансляции, отправив запрос с помощью различных методов Player и Timeline.Window, как описано ниже и показано на следующем рисунке.
Player.isCurrentWindowLiveуказывает, является ли воспроизводимый в данный момент мультимедийный объект прямой трансляцией. Это значение сохраняется, даже если трансляция уже завершена.Player.isCurrentWindowDynamicуказывает, обновляется ли воспроизводимый в данный момент мультимедийный объект. Обычно это происходит, если трансляция ещё не завершена. Обратите внимание, что в некоторых случаях этот флаг также имеет значение true для трансляций, которые не проводятся в прямом эфире.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. - Значения, считанные непосредственно из медиафайла.
Kotlin
// 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)
Java
// 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.
Аналогичным образом можно включить DVR для трансляций без низкой задержки, явно задав для этих параметров значения, отличные от 1.0f. Подробнее о том, как задать эти свойства, рассказывается в разделе о настройке.
Настройка алгоритма регулировки скорости воспроизведения
Если корректировка скорости включена, LivePlaybackSpeedControl определяет, какие корректировки вносятся. Вы можете реализовать собственный интерфейс LivePlaybackSpeedControl или настроить реализацию по умолчанию – DefaultLivePlaybackSpeedControl. В обоих случаях экземпляр можно задать при создании проигрывателя:
Kotlin
val player = ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build() ) .build()
Java
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
Позиция воспроизведения может отставать от окна прямой трансляции, например если проигрыватель приостановлен или буферизация длится слишком долго. В этом случае воспроизведение не удастся, и будет зарегистрировано исключение с кодом ошибки ERROR_CODE_BEHIND_LIVE_WINDOW с помощью Player.Listener.onPlayerError. В таких случаях можно возобновить воспроизведение с позиции по умолчанию. Пример такого подхода можно найти в классе PlayerActivity демонстрационного приложения.
Kotlin
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 } }
Java
@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 } }