System przechwytywania zwykle nagrywa strumienie wideo i audio, kompresuje je, multipleksuje oba strumienie, a następnie zapisuje wynikowy strumień na dysku.
W CameraX rozwiązaniem do nagrywania filmów jest przypadek użycia VideoCapture:
VideoCapture.Jak pokazano na rysunku 2, przechwytywanie wideo w CameraX obejmuje kilka komponentów architektury wysokiego poziomu:
SurfaceProviderjako źródło filmu.AudioSourcejako źródło dźwięku.- 2 kodery do kodowania i kompresowania obrazu i dźwięku;
- multiplekser multimediów do multipleksowania 2 strumieni.
- Zapisujący pliki, który zapisze wynik.
Interfejs VideoCapture API upraszcza złożony mechanizm przechwytywania i zapewnia aplikacjom znacznie prostszy i bardziej przejrzysty interfejs API.
Omówienie interfejsu VideoCapture API
VideoCapture to przypadek użycia CameraX, który dobrze sprawdza się samodzielnie lub w połączeniu z innymi przypadkami użycia. Konkretne obsługiwane kombinacje zależą od możliwości sprzętowych aparatu, ale Preview i VideoCapture to prawidłowa kombinacja przypadków użycia na wszystkich urządzeniach.
Interfejs VideoCapture API składa się z tych obiektów, które komunikują się z aplikacjami:
VideoCaptureto klasa przypadków użycia najwyższego poziomu.VideoCapturewiąże się zLifecycleOwnerza pomocąCameraSelectori innych UseCases CameraX. Więcej informacji o tych pojęciach i zastosowaniach znajdziesz w artykule Architektura CameraX.Recorderto implementacja VideoOutput, która jest ściśle powiązana zVideoCapture.Recordersłuży do nagrywania obrazu i dźwięku. Aplikacja tworzy nagrania zRecorder.PendingRecordingkonfiguruje nagrywanie, udostępniając opcje takie jak włączanie dźwięku i ustawianie detektora zdarzeń. Aby utworzyćPendingRecording, musisz użyćRecorder.PendingRecordingnie nagrywa niczego.Recordingwykonuje faktyczne nagranie. Aby utworzyćRecording, musisz użyćPendingRecording.
Rysunek 3 przedstawia relacje między tymi obiektami:
Legenda:
- Utwórz
Recorderza pomocąQualitySelector. - Skonfiguruj
Recorderza pomocą jednego zOutputOptions. - W razie potrzeby włącz dźwięk za pomocą
withAudioEnabled(). - Zadzwoń do
start()zVideoRecordEvent, aby rozpocząć nagrywanie. - Aby sterować nagrywaniem, użyj
pause()/resume()/stop()naRecording. - Odpowiedz na
VideoRecordEventsw detektorze zdarzeń.
Szczegółową listę interfejsów API znajdziesz w pliku current.txt w kodzie źródłowym.
Korzystanie z interfejsu VideoCapture API
Aby zintegrować przypadek użycia VideoCapture CameraX z aplikacją, wykonaj te czynności:
- Powiąż
VideoCapture. - Przygotuj i skonfiguruj nagrywanie.
- rozpoczynać i kontrolować nagrywanie środowiska wykonawczego;
W sekcjach poniżej opisujemy, co możesz zrobić na każdym etapie, aby uzyskać pełną sesję nagrywania.
Powiąż przechwytywanie wideo
Aby powiązać przypadek użycia VideoCapture, wykonaj te czynności:
- Utwórz obiekt
Recorder. - Utwórz obiekt
VideoCapture. - Powiąż z:
Lifecycle.
Interfejs CameraX VideoCapture API jest zgodny ze wzorcem projektowym kreatora. Aplikacje używają Recorder.Builder do tworzenia Recorder. Możesz też skonfigurować rozdzielczość wideo dla Recorder za pomocą obiektu QualitySelector.
CameraX Recorder obsługuje te wstępnie zdefiniowane Qualities rozdzielczości filmów:
Quality.UHDw przypadku rozmiaru filmu 4K Ultra HD (2160p)Quality.QHDdla rozmiaru wideo Quad HD (1440p), wprowadzona w CameraX1.7.0-alpha02Quality.FHDw przypadku rozmiaru wideo Full HD (1080p)Quality.HDw przypadku rozmiaru wideo HD (720p)Quality.SDw przypadku rozmiaru SD (480p),
Pamiętaj, że CameraX może też wybrać inne rozdzielczości, jeśli aplikacja na to zezwala.
Dokładny rozmiar filmu w przypadku każdej opcji zależy od możliwości kamery i kodera. Więcej informacji znajdziesz w dokumentacji CamcorderProfile.
Aplikacje mogą konfigurować rozdzielczość, tworząc obiekt QualitySelector.
Możesz utworzyć QualitySelector za pomocą jednej z tych metod:
Podaj kilka preferowanych rozdzielczości za pomocą
fromOrderedList()i uwzględnij strategię zastępczą, która zostanie użyta, jeśli żadna z preferowanych rozdzielczości nie będzie obsługiwana.CameraX może wybrać najlepsze dopasowanie zastępcze na podstawie możliwości wybranej kamery. Więcej informacji znajdziesz w
FallbackStrategy specification(QualitySelector). Na przykład ten kod żąda najwyższej obsługiwanej rozdzielczości nagrywania, a jeśli nie można obsłużyć żadnej z żądanych rozdzielczości, upoważnia CameraX do wybrania rozdzielczości najbliższej Quality.SD:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))Najpierw sprawdź możliwości aparatu i wybierz jedną z obsługiwanych rozdzielczości za pomocą
QualitySelector::from():val cameraInfo = cameraProvider.availableCameraInfos.filter { Camera2CameraInfo .from(it) .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK } val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0]) val filteredQualities = arrayListOf (Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD) .filter { supportedQualities.contains(it) } // Use a simple ListView with the id of simple_quality_list_view viewBinding.simpleQualityListView.apply { adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredQualities.map { it.qualityToString() }) // Set up the user interaction to manually show or hide the system UI. setOnItemClickListener { _, _, position, _ -> // Inside View.OnClickListener, // convert Quality.* constant to QualitySelector val qualitySelector = QualitySelector.from(filteredQualities[position]) // Create a new Recorder/VideoCapture for the new quality // and bind to lifecycle val recorder = Recorder.Builder() .setQualitySelector(qualitySelector).build() // ... } } // A helper function to translate Quality to a string fun Quality.qualityToString() : String { return when (this) { Quality.UHD -> "UHD" Quality.QHD -> "QHD" Quality.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }Pamiętaj, że funkcja zwrócona przez
QualitySelector.getSupportedQualities()będzie działać w przypadku użyciaVideoCapturelub kombinacji przypadków użyciaVideoCaptureiPreview. W przypadku powiązania z przypadkiem użyciaImageCapturelubImageAnalysisCameraX może nadal nie powiązać, jeśli wymagana kombinacja nie jest obsługiwana przez żądany aparat.
Gdy masz już QualitySelector, aplikacja może utworzyć obiekt VideoCapture i wykonać powiązanie. Pamiętaj, że to powiązanie jest takie samo jak w przypadku innych zastosowań:
val recorder = Recorder.Builder()
.setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
.build()
val videoCapture = VideoCapture.withOutput(recorder)
try {
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
Pamiętaj, że bindToLifecycle() zwraca obiekt Camera. Więcej informacji o sterowaniu obrazem z kamery, np. powiększeniem i ekspozycją, znajdziesz w tym przewodniku.
Recorder wybiera najbardziej odpowiedni format dla systemu. Najpopularniejszym kodekiem wideo jest H.264 AVC z formatem kontenera MPEG-4.
Konfigurowanie i tworzenie nagrania
Z poziomu Recorder aplikacja może tworzyć obiekty nagrywania, aby przechwytywać obraz i dźwięk. Aplikacje tworzą nagrania w ten sposób:
- Skonfiguruj
OutputOptionsza pomocąprepareRecording(). - (Opcjonalnie) Włącz nagrywanie dźwięku.
- Użyj
start(), aby zarejestrować detektorVideoRecordEventi rozpocząć nagrywanie filmu.
Gdy wywołasz funkcję start(), Recorder zwraca obiekt Recording.
Aplikacja może używać tego obiektu Recording do zakończenia przechwytywania lub wykonywania innych działań, takich jak wstrzymywanie lub wznawianie.
Recorder obsługuje tylko 1 obiekt Recording naraz. Możesz rozpocząć nowe nagrywanie po wywołaniu metody Recording.stop() lub Recording.close() na poprzednim obiekcie Recording.
Przyjrzyjmy się tym krokom bardziej szczegółowo. Najpierw aplikacja konfiguruje OutputOptions dla Dyktafonu z Recorder.prepareRecording().
Recorder obsługuje te typy OutputOptions:
FileDescriptorOutputOptions, aby przechwycić dane doFileDescriptor.FileOutputOptions, aby przechwycić je doFile.MediaStoreOutputOptions, aby przechwycić dane doMediaStore.
Wszystkie typy OutputOptions umożliwiają ustawienie maksymalnego rozmiaru pliku za pomocą setFileSizeLimit(). Inne opcje są specyficzne dla poszczególnych typów danych wyjściowych, np. ParcelFileDescriptor dla FileDescriptorOutputOptions.
prepareRecording() zwraca obiekt PendingRecording, który jest obiektem pośrednim używanym do utworzenia odpowiedniego obiektu Recording. PendingRecording to klasa przejściowa, która w większości przypadków powinna być niewidoczna i rzadko jest przechowywana w pamięci podręcznej aplikacji.
Aplikacje mogą dodatkowo konfigurować nagrywanie, na przykład:
- Włącz dźwięk za pomocą
withAudioEnabled(). - Zarejestruj detektor, aby otrzymywać zdarzenia nagrywania filmów za pomocą
start(Executor, Consumer<VideoRecordEvent>). - Zezwalaj na nagrywanie ciągłe, gdy obiekt VideoCapture, do którego jest dołączone, jest ponownie powiązany z inną kamerą, za pomocą
PendingRecording.asPersistentRecording().
Aby rozpocząć nagrywanie, zadzwoń pod numer PendingRecording.start(). CameraX przekształca PendingRecording w Recording, dodaje żądanie nagrywania do kolejki i zwraca nowo utworzony obiekt Recording do aplikacji.
Gdy rozpocznie się nagrywanie na odpowiednim urządzeniu z aparatem, CameraX wysyła zdarzenie VideoRecordEvent.EVENT_TYPE_START.
Poniższy przykład pokazuje, jak nagrać obraz i dźwięk do pliku MediaStore:
// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
.setContentValues(contentValues)
.build()
// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
.prepareRecording(context, mediaStoreOutput)
.withAudioEnabled()
.start(ContextCompat.getMainExecutor(this), captureListener)
Podgląd z przedniego aparatu jest domyślnie odbiciem lustrzanym, ale filmy nagrane za pomocą VideoCapture domyślnie nie są odbiciem lustrzanym. Dzięki CameraX 1.3 można teraz tworzyć lustrzane odbicia nagrań wideo, aby podgląd z przedniego aparatu i nagrany film były takie same.
Dostępne są 3 opcje MirrorMode: MIRROR_MODE_OFF, MIRROR_MODE_ON i MIRROR_MODE_ON_FRONT_ONLY. Aby dopasować obraz do podglądu z aparatu, Google zaleca użycie trybu MIROR_MODE_ON_FRONT_ONLY, co oznacza, że odbicie lustrzane nie jest włączone w przypadku tylnego aparatu, ale jest włączone w przypadku przedniego. Więcej informacji o MirrorMode znajdziesz tutaj: MirrorMode constants.
Ten fragment kodu pokazuje, jak wywołać VideoCapture.Builder.setMirrorMode() za pomocą MIRROR_MODE_ON_FRONT_ONLY. Więcej informacji znajdziesz w artykule setMirrorMode().
Kotlin
val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build() useCases.add(videoCapture);
Java
Recorder.Builder builder = new Recorder.Builder(); if (mVideoQuality != QUALITY_AUTO) { builder.setQualitySelector( QualitySelector.from(mVideoQuality)); } VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(builder.build()) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build(); useCases.add(videoCapture);
Zakres dynamiki (film HDR)
CameraX obsługuje 10-bitowe nagrywanie filmów w trybie High Dynamic Range (HDR), np. HLG10, HDR10, HDR10+ lub Dolby Vision, przy użyciu DynamicRange.
Aby nagrywać filmy w trybie HDR, wykonaj te czynności:
- Sprawdź obsługiwane przez aparat zakresy dynamiczne za pomocą
VideoCapabilities.getSupportedDynamicRanges(). - Opcjonalnie: jeśli skonfigurujesz niestandardowy parametr
QualitySelector, sprawdź, które jakości są obsługiwane w przypadku tego zakresu dynamicznego, używającgetSupportedQualities(DynamicRange). - Skonfiguruj
VideoCapture.Builderza pomocąsetDynamicRange().
Poniższy przykład umożliwia nagrywanie w 10-bitowym trybie HDR HLG, gdy aparat obsługuje tę funkcję:
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val supportedHdrRanges = videoCapabilities.supportedDynamicRanges .filter { it != DynamicRange.SDR } val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .apply { if (supportedHdrRanges.contains(DynamicRange.HLG_10_BIT)) { setDynamicRange(DynamicRange.HLG_10_BIT) } } .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); Set<DynamicRange> supportedRanges = videoCapabilities.getSupportedDynamicRanges(); Recorder recorder = new Recorder.Builder().build(); VideoCapture.Builder<Recorder> builder = new VideoCapture.Builder<>(recorder); if (supportedRanges.contains(DynamicRange.HLG_10_BIT)) { builder.setDynamicRange(DynamicRange.HLG_10_BIT); } VideoCapture<Recorder> videoCapture = builder.build();
Stabilizacja wideo
CameraX obsługuje stabilizację obrazu, aby zmniejszyć drgania i wstrząsy podczas nagrywania filmów.
Aby włączyć stabilizację obrazu, wykonaj te czynności:
- Sprawdź, czy aparat obsługuje stabilizację, używając
VideoCapabilities.isStabilizationSupported(). - Włącz go w
VideoCapture.Builderza pomocąsetVideoStabilizationEnabled(true).
Poniższy przykład włącza stabilizację, jeśli aparat ją obsługuje:
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val videoCapture = VideoCapture.Builder(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported) .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported()) .build();
Sterowanie aktywnym nagrywaniem
Możesz wstrzymać, wznowić i zatrzymać trwający Recording, korzystając z tych metod:
pause, aby wstrzymać bieżące aktywne nagrywanie.resume(), aby wznowić wstrzymane aktywne nagrywanie.stop(), aby zakończyć nagrywanie i usunąć wszystkie powiązane obiekty nagrywania.mute(), aby wyciszyć lub wyłączyć wyciszenie bieżącego nagrania.
Pamiętaj, że możesz wywołać metodę stop(), aby zakończyć Recording niezależnie od tego, czy nagrywanie jest wstrzymane czy aktywne.
Jeśli masz zarejestrowany EventListener w PendingRecording.start(), Recording komunikuje się za pomocą VideoRecordEvent.
VideoRecordEvent.EVENT_TYPE_STATUSsłuży do rejestrowania statystyk, takich jak bieżący rozmiar pliku i zarejestrowany przedział czasu.VideoRecordEvent.EVENT_TYPE_FINALIZEjest używany do zapisu wyniku nagrywania i zawiera informacje takie jak identyfikator URI pliku końcowego oraz powiązane błędy.
Gdy aplikacja otrzyma EVENT_TYPE_FINALIZE, który wskazuje na pomyślne zakończenie sesji nagrywania, możesz uzyskać dostęp do nagranego filmu z lokalizacji określonej w OutputOptions.
Amplituda i stan dźwięku w czasie rzeczywistym
Podczas nagrywania zdarzenia VideoRecordEvent.Status dostarczają statystyki dźwięku w czasie rzeczywistym za pomocą AudioStats:
AudioStats.getAudioAmplitude()zwraca bieżącą szczytową amplitudę dźwięku z zakresu od0.0do1.0. Możesz użyć tej wartości do sterowania miernikami interfejsu lub wizualizatorami fali dźwiękowej.AudioStats.getAudioState()wskazuje bieżący stan strumienia audio, np.AUDIO_STATE_ACTIVE,AUDIO_STATE_MUTEDlubAUDIO_STATE_SOURCE_SILENCED.
W tym przykładzie odczytywana jest amplituda dźwięku ze zdarzenia stanu:
Kotlin
when (event) { is VideoRecordEvent.Status -> { val audioStats = event.recordingStats.audioStats if (audioStats.hasAudio()) { val amplitude = audioStats.audioAmplitude updateAudioWaveform(amplitude) } } // ... }
Java
if (event instanceof VideoRecordEvent.Status) { VideoRecordEvent.Status status = (VideoRecordEvent.Status) event; AudioStats audioStats = status.getRecordingStats().getAudioStats(); if (audioStats.hasAudio()) { double amplitude = audioStats.getAudioAmplitude(); updateAudioWaveform(amplitude); } }
Filmy w trybie przyspieszonym i zwolnionym
CameraX obsługuje nagrywanie filmów z dużą szybkością, np. 120, 240 lub 480 kl./s, co umożliwia 2 różne zastosowania:
- Film z dużą liczbą klatek na sekundę (efekt zwolnionego tempa obsługiwany przez odtwarzacz): CameraX rejestruje i zapisuje klatki z dużą liczbą klatek na sekundę (np. 120 kl./s). Odtwarzacz wideo kontroluje szybkość odtwarzania, umożliwiając użytkownikom przełączanie się między normalną szybkością a zwolnionym tempem lub analizowanie klatka po klatce.
- Gotowy do odtworzenia film w zwolnionym tempie: CameraX przetwarza strumień o wysokiej szybkości i generuje standardowy plik wideo o częstotliwości 30 kl./s z dostosowanymi sygnaturami czasowymi klatek. Efekt zwolnionego tempa jest „wbudowany”, więc film jest automatycznie odtwarzany w zwolnionym tempie w każdym standardowym odtwarzaczu bez specjalnej obsługi. Na przykład nagranie z szybkością 120 kl./s odtwarzane z szybkością 30 kl./s daje film w zwolnionym tempie 1/4x.
Sprawdzanie możliwości szybkiego połączenia
Nagrywanie filmów z dużą szybkością wymaga obsługi sprzętowej i odpowiednich definicji CamcorderProfile od producentów urządzeń, takich jak CamcorderProfile.QUALITY_HIGH_SPEED_1080P lub QUALITY_HIGH_SPEED_720P.
Przed skonfigurowaniem nagrywania z dużą szybkością sprawdź możliwości nagrywania z dużą szybkością za pomocą metody Recorder.getHighSpeedVideoCapabilities(CameraInfo):
Kotlin
val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo) if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return } val supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR)
Java
VideoCapabilities highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo); if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return; } List<Quality> supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR);
Konfigurowanie HighSpeedVideoSessionConfig
Aby korzystać z szybkiego przechwytywania, połącz przypadki użycia VideoCapture i Preview w HighSpeedVideoSessionConfig. Aby skonfigurować sesję, wykonaj te czynności:
- Utwórz przypadek użycia
VideoCapturei przypadek użyciaPreview. - Zainicjuj
HighSpeedVideoSessionConfig.Builderz przypadkiem użyciaVideoCapturei dołączPreview. - Sprawdź obsługiwane zakresy liczby klatek za pomocą
CameraInfo.getSupportedFrameRateRanges(SessionConfig)i ustaw wybrany zakres. - Wybierz film z dużą liczbą klatek lub gotowy do odtworzenia film w zwolnionym tempie:
- Aby utworzyć film z dużą liczbą klatek, pozostaw wartość
setSlowMotionEnabled(false)(domyślna). - Aby utworzyć gotowy do odtworzenia film w zwolnionym tempie, wywołaj
setSlowMotionEnabled(true).
- Aby utworzyć film z dużą liczbą klatek, pozostaw wartość
- Powiąż konfigurację sesji za pomocą
cameraProvider.bindToLifecycle().
W przykładzie poniżej skonfigurowano i powiązano gotową do odtworzenia sesję w zwolnionym tempie:
Kotlin
val preview = Preview.Builder().build() val recorder = Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.first())) .build() val videoCapture = VideoCapture.withOutput(recorder) // Build HighSpeedVideoSessionConfig val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) // Enable automatic slow-motion playback at 30 fps .setSlowMotionEnabled(true) // Query and set a supported high-speed frame rate range (such as 120 or 240 fps). // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. val supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()) sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.first()) val sessionConfig = sessionConfigBuilder.build() // Bind session config to lifecycle cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig )
Java
Preview preview = new Preview.Builder().build(); Recorder recorder = new Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.get(0))) .build(); VideoCapture<Recorder> videoCapture = VideoCapture.withOutput(recorder); HighSpeedVideoSessionConfig.Builder sessionConfigBuilder = new HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) .setSlowMotionEnabled(true); // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. Set<Range<Integer>> supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()); sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.iterator().next()); HighSpeedVideoSessionConfig sessionConfig = sessionConfigBuilder.build(); cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig );
Możesz też użyć języka DSL w Kotlin, który został wprowadzony w CameraX 1.7.0-alpha02, aby szybko skonfigurować sesje o dużej szybkości:
val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
this.preview = preview
isSlowMotionEnabled = true
frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
sessionConfig
)
Nagrywanie filmów w trybie przyspieszonym lub w zwolnionym tempie
Po powiązaniu HighSpeedVideoSessionConfig rozpocznij nagrywanie za pomocą VideoCapture w taki sam sposób jak w przypadku standardowych nagrań wideo:
Kotlin
val recording = videoCapture.output .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context)) { event -> when (event) { is VideoRecordEvent.Start -> Log.d(TAG, "Recording started") is VideoRecordEvent.Finalize -> { if (!event.hasError()) { Log.d(TAG, "Video saved: ${event.outputResults.outputUri}") } } } }
Java
Recording recording = videoCapture.getOutput() .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context), event -> { if (event instanceof VideoRecordEvent.Start) { Log.d(TAG, "Recording started"); } else if (event instanceof VideoRecordEvent.Finalize) { VideoRecordEvent.Finalize finalize = (VideoRecordEvent.Finalize) event; if (!finalize.hasError()) { Log.d(TAG, "Video saved: " + finalize.getOutputResults().getOutputUri()); } } });
Dodatkowe materiały
Więcej informacji o CameraX znajdziesz w tych materiałach:
- Pierwsze kroki z CameraX – ćwiczenia z programowania
- Oficjalna przykładowa aplikacja CameraX
- Lista najnowszych interfejsów API CameraX Video Capture
- Informacje o wersji CameraX
- Kod źródłowy CameraX
- Szybkie nagrywanie i filmy w zwolnionym tempie dzięki CameraX 1.5