Wiadomości o usługach

Media3 1.9.0 – nowości

Czas czytania: 6 minut
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 się 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 uprościliśmy kilka funkcji ExoPlayerTransformerMediaSession

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


Czytaj dalej, aby dowiedzieć się więcej. 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 plik, jaki jest jego czas trwania lub pobrać miniatury.

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

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

Wartości MetadataRetrieverFrameExtractor 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 multimediów Material3 Compose w kilku krokach

W poprzednich wersjach udostępniliśmy 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 utworzyć 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. Więcej informacji o modułach interfejsu Compose znajdziesz na naszych stronach z rozszerzonymi przewodnikami.

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

 

obraz.png

Prosty interfejs odtwarzacza Compose z gotowymi elementami

Automatyczne przełączanie 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()

}
obraz.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 powiązać 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 PreloadManagerem

Ulepszyliśmy też nasze PreloadManager. Umożliwiało ono już wstępne wczytywanie multimediów do pamięci poza odtwarzaniem, a następnie płynne przekazywanie ich do odtwarzacza w razie potrzeby. Chociaż jest dość wydajny, 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 w wersji 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 wstępnie wczytywać znacznie większą liczbę elementów, ponieważ te, które są dalej od bieżącego elementu, nie muszą już zajmować pamięci. Pamiętaj, że wymaga to ustawienia CacheDefaultPreloadManager.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, ale możesz go skonfigurować w DefaultLoadControl.Builder. DefaultPreloadManager automatycznie przestanie wstępnie wczytywać treści 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 muteunmute, 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 nigdy nie zobaczysz tych problemów. Aby to ułatwić, odtwarzacz zgłasza teraz StuckPlayerException, gdy wykryje stan zawieszenia.
  • Domyślna blokada uśpienia – zarządzanie blokadą uśpienia było wcześniej opcjonalne, co utrudniało znajdowanie przypadków brzegowych, 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 Wear OS, 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 upraszcza to zadanie – możesz teraz określać preferencje dotyczące przycisków multimediów za pomocą standardowego polecenia odtwarzacza, bez konieczności obsługi poleceń niestandardowych.

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()
))
obraz.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 trakcie opracowywania. 

CompositionPlayer to nowy komponent w interfejsach Media3 Editing API, który umożliwia podgląd zmian w mediach w czasie rzeczywistym. CompositionPlayer, oparty na znanym interfejsie Media3 Player, umożliwia użytkownikom sprawdzenie wprowadzonych zmian przed rozpoczęciem procesu eksportowania. Używa tego samego obiektu Composition, który przekazujesz do funkcji Transformer na potrzeby eksportowania, co upraszcza przepływ pracy związany z edycją, ponieważ ujednolica model danych na potrzeby podglądu i eksportowania.

Zachęcamy do rozpoczęcia korzystania z CompositionPlayer i przesyłania opinii. Więcej szczegółów znajdziesz w przyszłych 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 Muxer Media3, co zapewnia spójne działanie we wszystkich wersjach interfejsu API. 

Pamiętaj, że Transformer nie używa już domyślnie MediaMuxer na platformie Android, ale w razie potrzeby możesz nadal dostarczać FrameworkMuxer.Factory za pomocą setMuxerFactory.

Nowe interfejsy API do dostosowywania prędkości

Wersja 1.9.0 upraszcza interfejsy API do dostosowywania szybkości w przypadku edycji multimediów. Wprowadziliśmy nowe metody bezpośrednio w EditedMediaItem.Builder, aby kontrolować szybkość, 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()

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 niezawodna 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 ułatwiające definiowanie sekwencji, aby uzyskać bardziej przejrzyste i niezawodne definicje.

Przykład tworzenia sekwencji zawierającej tylko filmy:

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

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

Autor:

Czytaj dalej