Wiadomości o usługach

Media3 1.9.0 – nowości

Czas czytania: 6 minut
Wyświetl profil Kristiny Simakovej
Kristina Simakova Menedżer ds. inżynierii

Wersja Media3 1.9.0 jest już dostępna. Oprócz zwykłych poprawek błędów i ulepszeń wydajności najnowsza wersja zawiera też 4 nowe lub w dużej mierze przepisane moduły:

  • media3-inspector – wyodrębnianie metadanych i klatek poza odtwarzaniem
  • media3-ui-compose-material3 – tworzenie podstawowego interfejsu multimediów w Compose w Material 3 w kilku krokach
  • media3-cast – automatyczne przełączanie między przesyłaniem a odtwarzaniem lokalnym;
  • media3-decoder-av1 – spójne odtwarzanie AV1 dzięki przepisaniu dekodera rozszerzenia na podstawie biblioteki dav1d.

Wprowadziliśmy też ulepszenia w zakresie buforowania i zarządzania pamięcią w PreloadManager oraz kilka nowych uproszczeń w ExoPlayer, Transformer i MediaSession. 

Ta wersja zapewnia też pierwszy eksperymentalny dostęp do CompositionPlayer, dzięki czemu możesz wyświetlać podgląd zmian w mediach.  


Aby dowiedzieć się więcej, czytaj dalej. Jak zawsze, pełne omówienie zmian w tej wersji znajdziesz w informacjach o wersji.

Wyodrębnianie metadanych i klatek poza odtwarzaniem

W wielu przypadkach możesz chcieć sprawdzić multimedia bez rozpoczynania odtwarzania. Możesz na przykład wykryć, jakie formaty zawiera, jaki jest jego czas trwania lub pobrać miniatury.

Nowy moduł media3-inspector łączy w jednym miejscu wszystkie narzędzia do sprawdzania multimediów bez odtwarzania:

  • MetadataRetriever, aby odczytywać czas trwania, format i statyczne metadane z MediaItem.
  • FrameExtractor, aby pobrać klatki lub miniatury z elementu.
  • MediaExtractorCompat jako bezpośredni zamiennik klasy MediaExtractor na platformie Android, aby uzyskać szczegółowe informacje o próbkach w pliku.

Wartości MetadataRetriever i FrameExtractor są zgodne z prostym wzorcem AutoCloseable. Więcej informacji znajdziesz na naszych nowych stronach z przewodnikami.

suspend fun extractThumbnail(mediaItem: MediaItem) {

  FrameExtractor.Builder(context, mediaItem).build().use {

    val thumbnail = frameExtractor.getThumbnail().await()

  } 

}

Tworzenie podstawowego interfejsu Material3 Compose Media w kilku krokach

W poprzednich wersjach zaczęliśmy udostępniać kod łączący elementy interfejsu Compose z instancją odtwarzacza. W Media3 w wersji 1.9.0 dodaliśmy nowy moduł media3-ui-compose-material3 z w pełni ostylowanymi przyciskami i elementami treści Material3. Pozwalają one zbudować interfejs multimedialny w kilku krokach, a jednocześnie zapewniają pełną elastyczność w dostosowywaniu stylu. Jeśli wolisz stworzyć własny styl interfejsu, możesz użyć elementów składowych, które obsługują całą logikę aktualizacji i połączeń. Dzięki temu możesz skupić się tylko na projektowaniu elementu interfejsu. Zapoznaj się z naszymi rozbudowanymi stronami przewodnika dotyczącymi modułów interfejsu Compose.

Pracujemy też nad kolejnymi komponentami Compose, takimi jak gotowy pasek przewijania, kompletny zamiennik elementu PlayerView, a także integracja napisów i reklam.

@Composable
fun SimplePlayerUI(player: Player, modifier: Modifier = Modifier) {
  Column(modifier) {
    ContentFrame(player)  // Video surface and shutter logic
    Row (Modifier.align(Alignment.CenterHorizontally)) {                 
      SeekBackButton(player)   // Simple controls
      PlayPauseButton(player)
      SeekForwardButton(player)
    }
  }
}

 

image.png

Prosty interfejs odtwarzacza Compose z gotowymi elementami

Automatyczne przełączanie się między przesyłaniem a odtwarzaniem lokalnym

Klasa CastPlayer w module media3-cast została przepisana, aby automatycznie obsługiwać przejścia między odtwarzaniem lokalnym (np. za pomocą ExoPlayer) a odtwarzaniem zdalnym za pomocą Cast.

Podczas konfigurowania MediaSession wystarczy utworzyć CastPlayer wokół ExoPlayer i dodać MediaRouteButton do interfejsu. Gotowe!

// MediaSession setup with CastPlayer 

val exoPlayer = ExoPlayer.Builder(context).build()

val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

val session = MediaSession.Builder(context, castPlayer).build()

// MediaRouteButton in UI 

@Composable fun UIWithMediaRouteButton() {

  MediaRouteButton()

}
image.png

Nowa integracja CastPlayer w aplikacji w wersji demonstracyjnej sesji Media3

Spójne odtwarzanie AV1 dzięki przepisanej wtyczce opartej na dav1d

Wersja 1.9.0 zawiera całkowicie przepisany moduł rozszerzenia AV1 oparty na popularnej bibliotece dav1d. 

Podobnie jak w przypadku wszystkich modułów dekodera rozszerzeń, pamiętaj, że wymaga on kompilacji ze źródeł , aby prawidłowo połączyć odpowiedni kod natywny. Dołączenie dekodera zapewnia spójność i obsługę formatów na wszystkich urządzeniach, ale ponieważ dekodowanie odbywa się w Twoim procesie, najlepiej nadaje się do treści, którym możesz zaufać. 

Zintegruj buforowanie i zarządzanie pamięcią z klasą PreloadManager

Ulepszyliśmy też nasze PreloadManager. Umożliwiało już wstępne wczytywanie multimediów do pamięci poza odtwarzaniem, a następnie płynne przekazywanie ich do odtwarzacza w razie potrzeby. Chociaż była dość wydajna, trzeba było uważać, aby nie przekroczyć limitów pamięci przez przypadkowe wstępne wczytanie zbyt dużej ilości danych. Dlatego w Media3 1.9.0 dodaliśmy 2 funkcje, które znacznie ułatwiają i stabilizują ten proces:

  1. Obsługa pamięci podręcznej  – podczas określania, jak daleko ma sięgać wstępne wczytywanie, możesz teraz wybrać PreloadStatus.specifiedRangeCached(0, 5000) jako stan docelowy wstępnie wczytanych elementów. Spowoduje to dodanie określonego zakresu do pamięci podręcznej na dysku zamiast wczytywania danych do pamięci. Dzięki temu możesz udostępnić do wstępnego wczytywania znacznie większy zakres elementów, ponieważ te, które są dalej od bieżącego elementu, nie muszą już zajmować pamięci. Pamiętaj, że wymaga to ustawienia Cache w DefaultPreloadManager.Builder.
  2. Automatyczne zarządzanie pamięcią  – zaktualizowaliśmy też interfejs LoadControl, aby lepiej obsługiwał wstępne wczytywanie. Możesz teraz ustawić wyraźny górny limit pamięci dla wszystkich wstępnie wczytanych elementów. Domyślnie wynosi on 144 MB, a limit możesz skonfigurować w DefaultLoadControl.Builder. DefaultPreloadManager automatycznie przestanie wstępnie wczytywać strony po osiągnięciu limitu i w razie potrzeby automatycznie zwolni pamięć zajmowaną przez elementy o niższym priorytecie.

Korzystaj z nowych, uproszczonych domyślnych zachowań w ExoPlayerze

Jak zawsze wprowadziliśmy też wiele drobnych ulepszeń w ExoPlayerze. Oto kilka przykładów:

  • Wyciszanie i wyłączanie wyciszenia – mieliśmy już metodę setVolume, ale teraz dodaliśmy wygodne metody mute i unmute, aby łatwo przywrócić poprzedni poziom głośności bez konieczności samodzielnego śledzenia go.
  • Wykrywanie zablokowanego odtwarzacza – w rzadkich przypadkach odtwarzacz może się zablokować w stanie buforowania lub odtwarzania bez postępów, np. z powodu problemów z kodekiem lub nieprawidłowej konfiguracji. Użytkownicy będą zirytowani, ale w statystykach nie zobaczysz tych problemów. Aby to ułatwić, odtwarzacz zgłasza teraz stan StuckPlayerException, gdy wykryje zablokowanie.
  • Domyślna blokada uśpienia – zarządzanie blokadą uśpienia było wcześniej opcjonalne, co powodowało trudne do znalezienia przypadki brzegowe, w których postęp odtwarzania mógł być znacznie opóźniony podczas działania w tle. Teraz ta funkcja jest opcjonalna, więc nie musisz się nią przejmować. Możesz też usunąć całą ręczną obsługę blokady uśpienia związaną z odtwarzaniem.
  • Uproszczone ustawienie logiki przycisku napisów – zmiana TrackSelectionParameters na „włącz/wyłącz napisy” okazała się zaskakująco trudna, dlatego dodaliśmy prostą opcję logiczną selectTextByDefault dla tego przypadku użycia.

Uproszczenie ustawień przycisków multimedialnych w MediaSession

Do tej pory określanie preferencji dotyczących przycisków, które mają się wyświetlać w panelu powiadomień o multimediach w Androidzie Auto lub WearOS, wymagało definiowania niestandardowych poleceń i przycisków, nawet jeśli wystarczyło wywołać standardową metodę odtwarzacza.

W Media3 w wersji 1.9.0 wprowadziliśmy nową funkcję, która znacznie ułatwia to zadanie – możesz teraz określić preferencje dotyczące przycisków multimediów za pomocą standardowego polecenia odtwarzacza, bez konieczności obsługi niestandardowych poleceń.

session.setMediaButtonPreferences(listOf(
    CommandButton.Builder(CommandButton.ICON_FAST_FORWARD) // choose an icon
      .setDisplayName(R.string.skip_forward)
      .setPlayerCommand(Player.COMMAND_SEEK_FORWARD) // choose an action 
      .build()
))
image.png

Ustawienia przycisków multimedialnych z przyciskiem przewijania do przodu

CompositionPlayer do podglądu w czasie rzeczywistym

W wersji 1.9.0 wprowadziliśmy CompositionPlayer z nową adnotacją @ExperimentalApi. Adnotacja wskazuje, że jest ona dostępna do eksperymentowania, ale nadal jest w fazie rozwoju. 

CompositionPlayer to nowy komponent w interfejsach Media3 API do edycji, który umożliwia podgląd zmian w mediach w czasie rzeczywistym. CompositionPlayer, oparty na znanym interfejsie Media3 Player, umożliwia użytkownikom sprawdzenie, jak działają wprowadzone zmiany, zanim zdecydują się na eksport. Używa tego samego obiektu Composition, który przekazujesz do funkcji Transformer na potrzeby eksportowania, co usprawnia proces edycji dzięki ujednoliceniu modelu danych na potrzeby podglądu i eksportu.

Zachęcamy do rozpoczęcia korzystania z CompositionPlayer i przesyłania opinii. Więcej szczegółów znajdziesz w nadchodzących postach i aktualizacjach dokumentacji.

InAppMuxer jako domyślny multiplekser w Transformerze

Transformer używa teraz InAppMp4Muxer jako domyślnego multipleksera do zapisywania plików kontenerów multimedialnych. Wewnętrznie InAppMp4Muxer zależy od modułu Media3 Muxer, co zapewnia spójne działanie we wszystkich wersjach interfejsu API. 

Pamiętaj, że Transformer nie używa już domyślnie interfejsu MediaMuxer platformy Android, ale w razie potrzeby możesz nadal udostępniać FrameworkMuxer.Factory za pomocą funkcji setMuxerFactory.

Nowe interfejsy API do dostosowywania prędkości

Wersja 1.9.0 upraszcza interfejsy API do dostosowywania szybkości podczas edycji multimediów. Wprowadziliśmy nowe metody bezpośrednio w EditedMediaItem.Builder, aby umożliwić kontrolowanie szybkości, dzięki czemu interfejs API jest bardziej intuicyjny. Możesz teraz zmienić szybkość klipu, wywołując setSpeed(SpeedProvider provider) na EditedMediaItem.Builder:

val speedProvider = object : SpeedProvider {
    override fun getSpeed(presentationTimeUs: Long): Float {
        return speed
    }

    override fun getNextSpeedChangeTimeUs(timeUs: Long): Long {
        return C.TIME_UNSET
    }
}

EditedMediaItem speedEffectItem = EditedMediaItem.Builder(mediaItem)
    .setSpeed(speedProvider)
    .build()

To nowe podejście zastępuje poprzednią metodę korzystania z Effects#createExperimentalSpeedChangingEffects(), którą wycofaliśmy i usuniemy w przyszłej wersji.

Przedstawiamy typy ścieżek dla EditedMediaItemSequence

W wersji 1.9.0 EditedMediaItemSequence wymaga określenia typów ścieżek wyjściowych podczas tworzenia sekwencji. Ta zmiana sprawia, że obsługa ścieżek jest bardziej jednoznaczna i solidna w całej kompozycji. 

Służy do tego nowy konstruktor EditedMediaItemSequence.Builder, który akceptuje zestaw typów ścieżek (np. C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO).

Aby uprościć tworzenie, dodaliśmy nowe statyczne metody ułatwiające:

  • EditedMediaItemSequence.withAudioFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withVideoFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withAudioAndVideoFrom(List<EditedMediaItem>)

Zachęcamy do przejścia na nowy konstruktor lub metody pomocnicze, aby uzyskać bardziej przejrzyste i niezawodne definicje sekwencji.

Przykład tworzenia sekwencji zawierającej tylko reklamy wideo:

EditedMediaItemSequence videoOnlySequence =
    EditedMediaItemSequence.Builder(setOf(C.TRACK_TYPE_VIDEO))
        .addItem(editedMediaItem)
        .build()

Jeśli napotkasz błędy lub masz pytania albo prośby o dodanie funkcji, skontaktuj się z nami za pomocą narzędzia do śledzenia problemów z Media3. Czekamy na wiadomość od Ciebie!

Autorzy:
Czytaj dalej