Instrukcje

Szybkie przechwytywanie i filmy w zwolnionym tempie w CameraX 1.5

6 min czytania
Wyświetl profil Charlesa Mungera
Leo Huang Software Engineer

Kluczową funkcją nowoczesnych aplikacji aparatu jest rejestrowanie szybko poruszających się obiektów z zachowaniem ostrości. Jest to możliwe dzięki szybkiemu przechwytywaniu, czyli procesowi rejestrowania klatek z szybkością np. 120 lub 240 kl./s. Takie przechwytywanie w wysokiej jakości może być używane do 2 różnych celów: tworzenia filmu z dużą liczbą klatek na sekundę do szczegółowej analizy klatka po klatce lub generowania filmu w zwolnionym tempie , w którym akcja rozwija się na ekranie w dramatyczny sposób.

Wcześniej implementowanie tych funkcji za pomocą interfejsu Camera2 API wymagało więcej pracy. Teraz dzięki nowemu interfejsowi API do szybkiego przechwytywania w CameraX 1.5 cały proces jest uproszczony, co daje Ci możliwość tworzenia filmów z dużą liczbą klatek na sekundę lub gotowych do odtworzenia klipów w zwolnionym tempie. W tym poście pokażemy Ci, jak opanować obie te techniki. Jeśli dopiero zaczynasz korzystać z CameraX, możesz zapoznać się z omówieniem CameraX.


Zasada działania zwolnionego tempa

Podstawową zasadą działania zwolnionego tempa jest rejestrowanie filmu z dużo większą liczbą klatek na sekundę niż podczas odtwarzania. Jeśli na przykład nagrasz sekundowe zdarzenie z szybkością 120 klatek na sekundę (kl./s), a następnie odtworzysz to nagranie ze standardową szybkością 30 kl./s, odtworzenie filmu zajmie 4 sekundy. To „rozciągnięcie” czasu tworzy dramatyczny efekt zwolnionego tempa, dzięki czemu możesz zobaczyć szczegóły, które są zbyt szybkie dla ludzkiego oka.

Aby końcowy film był płynny, powinien być renderowany z szybkością co najmniej 30 kl./s. Oznacza to, że aby utworzyć film w zwolnionym tempie 4-krotnie, oryginalna liczba klatek przechwytywania musi wynosić co najmniej 120 kl./s (120 kl./s ÷ 4 = 30 kl./s).

Po zarejestrowaniu materiału z dużą liczbą klatek na sekundę można osiągnąć pożądany efekt na 2 sposoby:

  • Zwolnione tempo obsługiwane przez odtwarzacz (film z dużą liczbą klatek na sekundę): nagranie z dużą szybkością (np.120 kl./s) jest zapisywane bezpośrednio jako plik wideo z dużą liczbą klatek na sekundę. Wtedy odtwarzacz wideo musi spowolnić szybkość odtwarzania. Dzięki temu użytkownik może przełączać się między normalnym odtwarzaniem a odtwarzaniem w zwolnionym tempie.
  • Zwolnione tempo gotowe do odtworzenia (ponownie zakodowany film): strumień wideo z dużą szybkością jest przetwarzany i ponownie kodowany do pliku ze standardową liczbą klatek na sekundę (np.30 kl./s). Efekt zwolnionego tempa jest „wypalany” przez dostosowanie sygnatur czasowych klatek. Wynikowy film będzie odtwarzany w zwolnionym tempie w każdym standardowym odtwarzaczu wideo bez specjalnej obsługi. Chociaż film jest domyślnie odtwarzany w zwolnionym tempie, odtwarzacze wideo mogą nadal udostępniać elementy sterujące szybkością odtwarzania, które pozwalają użytkownikowi zwiększyć szybkość i obejrzeć film z jego pierwotną szybkością.

Interfejs CameraX API upraszcza ten proces, umożliwiając Ci wybranie podejścia w jednolity sposób, jak zobaczysz poniżej.


Nowy interfejs API do szybkiego przechwytywania wideo

Nowe rozwiązanie CameraX składa się z 2 głównych komponentów:

  • Recorder#getHighSpeedVideoCapabilities(CameraInfo): ta metoda pozwala sprawdzić, czy aparat może nagrywać w trybie szybkiego przechwytywania, a jeśli tak, to jakie rozdzielczości (Quality objects) są obsługiwane.
  • HighSpeedVideoSessionConfig: jest to specjalny obiekt konfiguracji, który grupuje przypadki użycia VideoCapture i Preview, informując CameraX o konieczności utworzenia ujednoliconej sesji aparatu z szybkim przechwytywaniem. Pamiętaj, że chociaż strumień VideoCapture będzie działać z skonfigurowaną dużą liczbą klatek na sekundę, strumień Preview będzie zwykle ograniczony do standardowej szybkości co najmniej 30 kl./s przez system aparatu, aby zapewnić płynne wyświetlanie na ekranie.

Pierwsze kroki

Zanim zaczniesz, upewnij się, że do pliku build.gradle.kts aplikacji zostały dodane niezbędne zależności CameraX. Oprócz podstawowych bibliotek CameraX będziesz potrzebować artefaktu camera-video.

// build.gradle.kts (Module: app)

dependencies {

    val camerax_version = "1.5.1"


    implementation("androidx.camera:camera-core:$camerax_version")

    implementation("androidx.camera:camera-camera2:$camerax_version")

    implementation("androidx.camera:camera-lifecycle:$camerax_version")

    implementation("androidx.camera:camera-video:$camerax_version")

    implementation("androidx.camera:camera-view:$camerax_version")

}

Uwaga dotycząca eksperymentalnych interfejsów API

Pamiętaj, że interfejsy API do szybkiego przechwytywania są obecnie eksperymentalne. Oznacza to, że w przyszłych wersjach mogą ulec zmianie. Aby z nich korzystać, musisz wyrazić zgodę, dodając do kodu tę adnotację:

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

Implementacja

Implementacja obu rozwiązań zaczyna się od tych samych czynności konfiguracyjnych. Wybór między utworzeniem filmu z dużą liczbą klatek na sekundę a filmu w zwolnionym tempie sprowadza się do jednego ustawienia.

1. Skonfiguruj szybkie przechwytywanie

Najpierw, niezależnie od celu, musisz uzyskać ProcessCameraProvider, sprawdzić możliwości urządzenia i utworzyć przypadki użycia.

Poniższy blok kodu pokazuje pełny proces konfiguracji w funkcji zawieszenia. Tę funkcję możesz wywołać z zakresu współprogramu, np. lifecycleScope.launch.

// Add the OptIn annotation at the top of your function or class

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

private suspend fun setupCamera() {

    // Asynchronously get the CameraProvider

    val cameraProvider = ProcessCameraProvider.awaitInstance(this)



    // -- CHECK CAPABILITIES --

    val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA)

    val videoCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

    if (videoCapabilities == null) {

        // This camera device does not support high-speed video.

        return

    }




    // -- CREATE USE CASES --

    val preview = Preview.Builder().build()    


    // You can create a Recorder with default settings.

    // CameraX will automatically select a suitable quality.

    val recorder = Recorder.Builder().build()


    // Alternatively, to use a specific resolution, you can configure the
    // Recorder with a QualitySelector. This is useful if your app has
    // specific resolution requirements or you want to offer user
    // preferences. 

    // To use a specific quality, you can uncomment the following lines.

    // Get the list of qualities supported for high-speed video. 

    // val supportedQualities = videoCapabilities.getSupportedQualities(DynamicRange.SDR)

    // Build the Recorder using the quality from the supported list.

    // val recorderWithQuality = Recorder.Builder()

    //     .setQualitySelector(QualitySelector.from(supportedQualities.first()))

    //     .build()



    // Create the VideoCapture use case, using either recorder or recorderWithQuality

    val videoCapture = VideoCapture.withOutput(recorder)

    // Now you are ready to configure the session for your desired output...

}

2. Wybierz dane wyjściowe

Teraz zdecyduj, jaki rodzaj filmu chcesz utworzyć. Ten kod będzie działać w funkcji setupCamera() suspend pokazanej powyżej.

Opcja A. Utwórz film z dużą liczbą klatek na sekundę

Wybierz tę opcję, jeśli chcesz, aby plik końcowy miał dużą liczbę klatek na sekundę (np.film 120 kl./s).

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)


// Query and apply a supported frame rate. Common supported frame rates include 120 and 240 fps.

val supportedFrameRateRanges =

    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())


sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Opcja B. Utwórz film w zwolnionym tempie gotowy do odtworzenia

Wybierz tę opcję, jeśli chcesz, aby film był automatycznie odtwarzany w zwolnionym tempie w każdym standardowym odtwarzaczu wideo.

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)



// This is the key: enable automatic slow-motion!

sessionConfigBuilder.setSlowMotionEnabled(true)



// Query and apply a supported frame rate. Common supported frame rates include 120, 240, and 480 fps.

val supportedFrameRateRanges =

   cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())

sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Ten pojedynczy przełącznik jest kluczem do utworzenia filmu w zwolnionym tempie gotowego do odtworzenia. Gdy setSlowMotionEnabled ma wartość true, CameraX przetwarza strumień z dużą szybkością i zapisuje go jako standardowy plik wideo 30 kl./s. Szybkość zwolnionego tempa jest określana przez stosunek szybkości przechwytywania do tej standardowej szybkości odtwarzania.

Przykład:

  • Nagrywanie z szybkością 120 kl./s spowoduje utworzenie filmu, który będzie odtwarzany z szybkością 1/4x (120 ÷ 30 = 4).
  • Nagrywanie z szybkością 240 kl./s spowoduje utworzenie filmu, który będzie odtwarzany z szybkością 1/8x (240 ÷ 30 = 8).

Podsumowanie: nagrywanie filmu

Gdy skonfigurujesz HighSpeedVideoSessionConfig i powiążesz go z cyklem życia, ostatnim krokiem jest rozpoczęcie nagrywania. Proces przygotowywania opcji wyjściowych, rozpoczynania nagrywania i obsługi zdarzeń wideo jest taki sam jak w przypadku standardowego przechwytywania wideo.

Ten post skupia się na konfiguracji szybkiego przechwytywania, więc nie będziemy szczegółowo omawiać procesu nagrywania. Aby uzyskać wyczerpujące informacje na temat wszystkich aspektów, od przygotowania obiektu FileOutputOptions lub MediaStoreOutputOptions po obsługę wywołań zwrotnych VideoRecordEvent, zapoznaj się z dokumentacją VideoCapture.

// Bind the session config to the lifecycle

cameraProvider.bindToLifecycle(

    this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA,

    sessionConfigBuilder.build() // Bind the config object from Option A or B

)



// Start the recording using the VideoCapture use case

val recording = videoCapture.output

    .prepareRecording(context, outputOptions) // See docs for creating outputOptions

    .start(ContextCompat.getMainExecutor(context)) { recordEvent ->

        // Handle recording events (e.g., Start, Pause, Finalize)

    }

Obsługa filmów w zwolnionym tempie w Zdjęciach Google

Gdy włączysz setSlowMotionEnabled(true) w CameraX, wynikowy plik wideo będzie od razu rozpoznawany i odtwarzany w zwolnionym tempie w standardowych odtwarzaczach wideo i aplikacjach galerii. Zdjęcia Google oferują rozszerzone funkcje w przypadku tych filmów w zwolnionym tempie, gdy liczba klatek wynosi 120, 240, 360, 480 lub 960 kl./s:

  • Rozpoznawanie w interfejsie na miniaturze: w bibliotece Zdjęć Google filmy w zwolnionym tempie można rozpoznać po określonych elementach interfejsu, które odróżniają je od zwykłych filmów.
normal.png
slowmotion.png
Miniatura zwykłego filmuMiniatura filmu w zwolnionym tempie
  • Regulowane segmenty szybkości podczas odtwarzania: podczas odtwarzania filmu w zwolnionym tempie Zdjęcia Google udostępniają elementy sterujące, które pozwalają dostosować, które części filmu mają być odtwarzane w zwolnionym tempie, a które w normalnym tempie, co daje użytkownikom większą kontrolę nad kreatywnością. Edytowany film można następnie wyeksportować jako nowy plik wideo za pomocą przycisku Udostępnij, zachowując zdefiniowane segmenty w zwolnionym tempie.
normal2.png
slowmotion2.png
Odtwarzanie zwykłego filmuOdtwarzanie filmu w zwolnionym tempie 
z elementami sterującymi 
edycją

Uwaga dotycząca obsługi urządzeń

Interfejs API do szybkiego przechwytywania w CameraX korzysta z podstawowego systemu Androida CamcorderProfile, aby określić, jakie rozdzielczości i szybkości przechwytywania obsługuje urządzenie. Profile Camcorder są weryfikowane przez pakiet CTS (Android Compatibility Test Suite), co oznacza, że możesz mieć pewność, że urządzenie zgłasza prawidłowe możliwości nagrywania wideo.

Oznacza to, że możliwość nagrywania filmów w zwolnionym tempie za pomocą wbudowanej aplikacji aparatu nie gwarantuje, że interfejs API do szybkiego przechwytywania w CameraX będzie działać. Ta rozbieżność występuje, ponieważ producenci urządzeń są odpowiedzialni za wypełnianie wpisów CamcorderProfile w oprogramowaniu urządzenia, a czasami nie są uwzględniane niezbędne profile szybkiego przechwytywania, takie jak CamcorderProfile.QUALITY_HIGH_SPEED_1080P i CamcorderProfile.QUALITY_HIGH_SPEED_720P. Gdy te profile są niedostępne, Recorder.getHighSpeedVideoCapabilities() zwraca wartość null.

Dlatego zawsze należy używać Recorder.getHighSpeedVideoCapabilities() do programowego sprawdzania obsługiwanych funkcji, ponieważ jest to najbardziej niezawodny sposób na zapewnienie spójnego działania na różnych urządzeniach. Jeśli spróbujesz powiązać HighSpeedVideoSessionConfig na urządzeniu, na którym Recorder.getHighSpeedVideoCapabilities() zwraca wartość null, operacja zakończy się niepowodzeniem z powodu IllegalArgumentException. Obsługę możesz potwierdzić na urządzeniach Google Pixel, ponieważ zawsze zawierają one te profile szybkiego przechwytywania. Ponadto różne urządzenia innych producentów, takie jak Motorola Edge 30, OPPO Find N2 Flip i Sony Xperia 1 V, również obsługują szybkie przechwytywanie wideo.


Podsumowanie

Interfejs API do szybkiego przechwytywania wideo w CameraX jest zarówno zaawansowany, jak i elastyczny. Niezależnie od tego, czy potrzebujesz materiału z dużą liczbą klatek na sekundę do analizy technicznej, czy chcesz dodać do aplikacji kinowe efekty zwolnionego tempa, HighSpeedVideoSessionConfig zapewnia ujednolicone i proste rozwiązanie. Dzięki zrozumieniu roli przełącznika setSlowMotionEnabled możesz łatwo obsługiwać oba przypadki użycia i dać użytkownikom większą kontrolę nad kreatywnością.

Czytaj dalej