ExoPlayer odtwarza większość adaptacyjnych transmisji na żywo od razu, bez specjalnej konfiguracji. Więcej informacji znajdziesz na stronie Obsługiwane formaty.
Adaptacyjne transmisje na żywo oferują okno dostępnych multimediów, które jest aktualizowane w regularnych odstępach czasu, aby dostosowywać się do bieżącego czasu rzeczywistego. Oznacza to, że pozycja odtwarzania będzie zawsze mieścić się w tym przedziale, w większości przypadków blisko bieżącego czasu rzeczywistego, w którym strumień jest generowany. Różnica między bieżącym czasem rzeczywistym a pozycją odtwarzania jest nazywana przesunięciem na żywo.
Wykrywanie i monitorowanie odtwarzania na żywo
Za każdym razem, gdy okno na żywo jest aktualizowane, zarejestrowane Player.ListenerinstancjeonTimelineChanged otrzymają zdarzenie onTimelineChanged. Szczegóły dotyczące bieżącego odtwarzania na żywo możesz pobrać, wysyłając zapytania do różnych metod Player i Timeline.Window, jak pokazano poniżej i na ilustracji.

Player.isCurrentWindowLivewskazuje, czy aktualnie odtwarzany element multimedialny jest transmisją na żywo. Ta wartość jest nadal prawdziwa, nawet jeśli transmisja na żywo się zakończyła.Player.isCurrentWindowDynamicwskazuje, czy aktualnie odtwarzany element multimedialny jest nadal aktualizowany. Zwykle dotyczy to transmisji na żywo, które nie zostały jeszcze zakończone. Pamiętaj, że w niektórych przypadkach ta flaga jest też ustawiona w przypadku transmisji, które nie są na żywo.Player.getCurrentLiveOffsetzwraca przesunięcie między bieżącym czasem rzeczywistym a pozycją odtwarzania (jeśli jest dostępna).Player.getDurationzwraca długość bieżącego okna transmisji na żywo.Player.getCurrentPositionzwraca pozycję odtwarzania względem początku okna transmisji na żywo.Player.getCurrentMediaItemzwraca bieżący element multimedialny, gdzieMediaItem.liveConfigurationzawiera podane przez aplikację zastąpienia parametrów docelowego przesunięcia na żywo i korekty przesunięcia na żywo.Player.getCurrentTimelinezwraca bieżącą strukturę multimediów wTimeline. Bieżącą wartośćTimeline.Windowmożna pobrać zTimelineza pomocąPlayer.getCurrentMediaItemIndexiTimeline.getWindow. W sekcjiWindow:Window.liveConfigurationzawiera parametry docelowego przesunięcia transmisji na żywo i korekty przesunięcia transmisji na żywo. Wartości te są oparte na informacjach w mediach i wszelkich zastąpieniach podanych przez aplikację, które zostały ustawione wMediaItem.liveConfiguration.Window.windowStartTimeMsto czas od początku epoki systemu Unix, w którym rozpoczyna się okno transmisji na żywo.Window.getCurrentUnixTimeMsto czas od początku epoki systemu Unix do bieżącego czasu rzeczywistego. Ta wartość może zostać skorygowana o znaną różnicę w zegarach serwera i klienta.Window.getDefaultPositionMsto pozycja w oknie transmisji na żywo, od której odtwarzacz domyślnie rozpocznie odtwarzanie.
Przewijanie transmisji na żywo
Możesz przewinąć transmisję do dowolnego momentu, korzystając z przycisku Player.seekTo. Przekazana pozycja wyszukiwania jest względna w stosunku do początku okna transmisji na żywo. Na przykład naciśnięcie klawisza seekTo(0) spowoduje przejście do początku okna transmisji na żywo. Po przewinięciu odtwarzacz spróbuje zachować ten sam offset transmisji na żywo co pozycja, do której przewinięto.
Okno transmisji na żywo ma też domyślną pozycję, od której ma się rozpocząć odtwarzanie. Zwykle znajduje się on w pobliżu krawędzi na żywo. Możesz przejść do pozycji domyślnej, wywołując funkcję Player.seekToDefaultPosition.
Interfejs odtwarzania na żywo
Domyślne komponenty interfejsu ExoPlayera pokazują czas trwania okna transmisji na żywo i bieżącą pozycję odtwarzania w tym oknie. Oznacza to, że pozycja będzie się cofać za każdym razem, gdy okno transmisji na żywo zostanie zaktualizowane. Jeśli potrzebujesz innego działania, np. wyświetlania czasu uniksowego lub bieżącego przesunięcia na żywo, możesz utworzyć fork PlayerControlView i zmodyfikować go zgodnie z własnymi potrzebami.
Konfigurowanie parametrów odtwarzania na żywo
ExoPlayer używa niektórych parametrów do kontrolowania przesunięcia pozycji odtwarzania względem krawędzi transmisji na żywo oraz zakresu szybkości odtwarzania, które można wykorzystać do dostosowania tego przesunięcia.
ExoPlayer pobiera wartości tych parametrów z 3 miejsc w kolejności malejącej priorytetu (używana jest pierwsza znaleziona wartość):
- Na
MediaItemwartości przekazywane doMediaItem.Builder.setLiveConfiguration. - Domyślne wartości globalne ustawione w
DefaultMediaSourceFactory. - wartości odczytywane bezpośrednio z nośnika,
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);
Dostępne wartości konfiguracyjne:
targetOffsetMs: docelowe przesunięcie transmisji na żywo. Odtwarzacz będzie próbował zbliżyć się do tego przesunięcia na żywo podczas odtwarzania, jeśli to możliwe.minOffsetMs: Minimalny dopuszczalny offset na żywo. Nawet jeśli dostosujesz przesunięcie do bieżących warunków sieci, odtwarzacz nie będzie próbował zejść poniżej tego przesunięcia podczas odtwarzania.maxOffsetMs: Maksymalny dozwolony offset transmisji na żywo. Nawet jeśli dostosujesz przesunięcie do bieżących warunków sieci, odtwarzacz nie będzie próbował przekroczyć tego przesunięcia podczas odtwarzania.minPlaybackSpeed: minimalna szybkość odtwarzania, której odtwarzacz może użyć, aby wrócić do poprzedniej wartości, gdy próbuje osiągnąć docelowe przesunięcie transmisji na żywo.maxPlaybackSpeed: maksymalna szybkość odtwarzania, której odtwarzacz może użyć, aby nadrobić zaległości podczas próby osiągnięcia docelowego przesunięcia transmisji na żywo.
Dostosowywanie szybkości odtwarzania
Podczas odtwarzania transmisji na żywo z krótkim czasem oczekiwania ExoPlayer dostosowuje przesunięcie transmisji na żywo, nieznacznie zmieniając szybkość odtwarzania. Odtwarzacz spróbuje dopasować docelowe przesunięcie na żywo podane przez media lub aplikację, ale będzie też reagować na zmieniające się warunki sieciowe. Jeśli na przykład podczas odtwarzania wystąpi ponowne buforowanie, odtwarzacz nieco zwolni odtwarzanie, aby oddalić się od krawędzi transmisji na żywo. Jeśli sieć stanie się wystarczająco stabilna, aby ponownie umożliwić odtwarzanie bliżej krawędzi transmisji na żywo, odtwarzacz przyspieszy odtwarzanie, aby wrócić do docelowego przesunięcia transmisji na żywo.
Jeśli automatyczne dostosowywanie szybkości odtwarzania nie jest pożądane, można je wyłączyć, ustawiając właściwości minPlaybackSpeed i maxPlaybackSpeed na 1.0f.
Podobnie można ją włączyć w przypadku transmisji na żywo o niskim opóźnieniu, ustawiając te wartości na inne niż 1.0f. Więcej informacji o tym, jak ustawić te właściwości, znajdziesz w sekcji konfiguracji powyżej.
Dostosowywanie algorytmu dostosowywania szybkości odtwarzania
Jeśli dostosowywanie szybkości jest włączone, LivePlaybackSpeedControl określa, jakie zmiany są wprowadzane. Możesz wdrożyć niestandardową implementację
LivePlaybackSpeedControl lub dostosować implementację domyślną, która jest
DefaultLivePlaybackSpeedControl. W obu przypadkach instancję można ustawić podczas tworzenia odtwarzacza:
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();
Odpowiednie parametry dostosowywania DefaultLivePlaybackSpeedControl to:
fallbackMinPlaybackSpeedifallbackMaxPlaybackSpeed: minimalna i maksymalna szybkość odtwarzania, których można użyć do dostosowania, jeśli ani multimedia, ani dostarczony przez aplikacjęMediaItemnie definiują limitów.proportionalControlFactor: określa, jak płynne jest dostosowanie szybkości. Wysoka wartość sprawia, że zmiany są bardziej nagłe i reaktywne, ale też bardziej słyszalne. Mniejsza wartość zapewnia płynniejsze przejście między prędkościami, ale kosztem mniejszej szybkości.targetLiveOffsetIncrementOnRebufferMs: ta wartość jest dodawana do docelowego przesunięcia na żywo za każdym razem, gdy występuje ponowne buforowanie, aby zachować większą ostrożność. Tę funkcję można wyłączyć, ustawiając wartość 0.minPossibleLiveOffsetSmoothingFactor: współczynnik wygładzania wykładniczego, który służy do śledzenia minimalnego możliwego przesunięcia na żywo na podstawie aktualnie buforowanych multimediów. Wartość bardzo zbliżona do 1 oznacza, że szacowanie jest bardziej ostrożne i może dłużej dostosowywać się do lepszych warunków sieciowych. Z kolei niższa wartość oznacza, że szacowanie będzie szybciej dostosowywać się do lepszych warunków sieciowych, ale wiąże się z większym ryzykiem ponownego buforowania.
BehindLiveWindowException i ERROR_CODE_BEHIND_LIVE_WINDOW
Pozycja odtwarzania może być opóźniona w stosunku do okna transmisji na żywo, np. jeśli odtwarzacz jest wstrzymany lub buforuje dane przez wystarczająco długi czas. Jeśli tak się stanie, odtwarzanie się nie powiedzie, a wyjątek z kodem błędu ERROR_CODE_BEHIND_LIVE_WINDOW zostanie zgłoszony za pomocą Player.Listener.onPlayerError. Kod aplikacji może obsługiwać takie błędy, wznawiając odtwarzanie w domyślnym miejscu. PlayerActivity w aplikacji w wersji demonstracyjnej jest przykładem takiego podejścia.
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 } }