System przechwytujący zwykle nagrywa, kompresuje i kompresuje strumienie audio i wideo. mapuje oba strumienie, a następnie zapisuje wynikowy strumień na dysku.
W Aparacie X rozwiązaniem do nagrywania wideo jest
VideoCapture
przypadek użycia:
Jak widać na ilustracji 2, nagrywanie wideo w aparacie X obejmuje kilka elementy architektoniczne:
SurfaceProvider
dla źródła filmu.AudioSource
jako źródło dźwięku.- Dwa kodery do kodowania i kompresji obrazu i dźwięku.
- Mukser multimediów do łączenia 2 strumieni.
- Wygaszacz plików umożliwiający zapisanie wyniku.
Interfejs VideoCapture API wyodrębnia złożony mechanizm przechwytywania i zapewnia do aplikacji za pomocą znacznie prostszego i prostszego interfejsu API.
Omówienie interfejsu VideoCapture API
VideoCapture
to przypadek użycia AparatuX, który działa dobrze samodzielnie lub gdy
w połączeniu z innymi zastosowaniami. Konkretne obsługiwane kombinacje zależą od
aparatów, jednak Preview
i VideoCapture
to
prawidłową kombinację przypadków użycia na wszystkich urządzeniach.
Interfejs VideoCapture API składa się z następujących obiektów, które komunikują się z aplikacjami:
VideoCapture
to najwyższego poziomu.VideoCapture
wiąże się zLifecycleOwner
zCameraSelector
i innym aparatemX Przypadki użycia. Więcej informacji o tych pojęciach i zastosowaniach znajdziesz tutaj: Architektura CameraX.Recorder
to implementacja VideoOutput, która jest ściśle powiązana z funkcjąVideoCapture
.Recorder
służy do nagrywania obrazu i dźwięku. An aplikacja tworzy nagrania zRecorder
.PendingRecording
konfiguruje nagranie, udostępniając opcje takie jak włączenie dźwięku detektorem zdarzeń. Aby utworzyćPendingRecording
, musisz użyć właściwościRecorder
.PendingRecording
niczego nie nagrywa.Recording
wykonuje działanie nagranie. Aby utworzyćRecording
, musisz użyć właściwościPendingRecording
.
Rysunek 3 pokazuje zależności między tymi obiektami:
Legenda:
- Utwórz
Recorder
z:QualitySelector
- Skonfiguruj w
Recorder
jedną z tych opcji:OutputOptions
- Włącz dźwięk za pomocą
withAudioEnabled()
w razie potrzeby. - Zadzwoń pod numer
start()
zVideoRecordEvent
aby rozpocząć nagrywanie. - Użyj
pause()
/resume()
/stop()
naRecording
aby sterować nagrywaniem. - Odpowiedz na pytanie
VideoRecordEvents
w detektorze zdarzeń.
Szczegółowa lista interfejsów API znajduje się 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.
- Możesz uruchamiać nagrywanie w czasie działania i nimi zarządzać.
W sekcjach poniżej opisano, co można zrobić na każdym etapie, aby uzyskać i całej sesji nagraniowej.
Powiąż przechwytywanie wideo
Aby powiązać przypadek użycia VideoCapure
, wykonaj te czynności:
- Utwórz obiekt
Recorder
. - Utwórz obiekt
VideoCapture
. - Powiąż z elementem
Lifecycle
.
Interfejs CameraX VideoCapture API zgodny ze wzorcem projektowania kreatora. Aplikacje
Użyj narzędzia Recorder.Builder
, aby utworzyć Recorder
. Możesz też skonfigurować
rozdzielczość wideo dla interfejsu Recorder
za pomocą obiektu QualitySelector
.
Aparat CameraX Recorder
obsługuje następujące wstępnie zdefiniowane pliki Qualities
dla rozdzielczości wideo:
Quality.UHD
– film w rozdzielczości 4K Ultra HD (2160p)Quality.FHD
– rozmiar filmu w jakości Full HD (1080p)Quality.HD
w przypadku filmu w rozmiarze HD (720p)Quality.SD
– rozmiar filmu w jakości SD (480p)
Pamiętaj, że CameraX może też wybrać inne rozdzielczości, jeśli zezwoli na to aplikacja.
Dokładny rozmiar filmu w przypadku każdej z wybranych opcji zależy od kamery i kodera
funkcje zabezpieczeń. Więcej informacji znajdziesz w dokumentacji
CamcorderProfile
Aplikacje mogą skonfigurować rozdzielczość, tworząc
QualitySelector
QualitySelector
możesz utworzyć, korzystając z jednej z tych metod:
Podaj kilka preferowanych rozdzielczości za pomocą parametru
fromOrderedList()
. zawierać strategię zastępczą, którą można zastosować, gdy żaden z obsługiwane są preferowane rozdzielczości.Aparat X może wybrać najlepsze dopasowanie kreacji zastępczej na podstawie Więcej informacji znajdziesz w artykule
FallbackStrategy specification
usługiQualitySelector
. . Na przykład poniższy kod żąda największej obsługiwanej liczby rozwiązanie nagrywania. Jeśli nie można zastosować żadnego z tych rozwiązań, autoryzuj urządzenie CameraX do wyboru takiej, która ma rozdzielczość najbliższą jakości.SD:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
Najpierw zapytaj o możliwości kamery, a następnie wybierz jedną z obsługiwanych rozdzielczości w formacie
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.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.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }
Zwróć uwagę, że zwrócona możliwość z
QualitySelector.getSupportedQualities()
na pewno sprawdzi się zarówno w przypadku użyciaVideoCapture
, jak i kombinacji przypadków użyciaVideoCapture
iPreview
. Podczas wiązania razem z Przypadek użyciaImageCapture
lubImageAnalysis
, CameraX powiązanie może nadal nie zostać zrealizowane, jeśli wymagana kombinacja nie jest obsługiwana w żądanej kamery.
Gdy masz QualitySelector
, aplikacja może utworzyć
VideoCapture
obiekt i wykonaj powiązanie. Zwróć uwagę, że to powiązanie jest
tak samo jak w innych przypadkach użycia:
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 wyjściem aparatu, np. powiększeniem i ekspozycją, znajdziesz w tym przewodniku.
Recorder
wybiera najbardziej odpowiedni format dla systemu. Najbardziej
Typowy kodek wideo to
H.264 AVC) z
format kontenera
MPEG-4
Skonfiguruj i utwórz nagranie
W Recorder
aplikacja może tworzyć obiekty rejestrujące
na potrzeby nagrywania obrazu i dźwięku. Aplikacje tworzą nagrania przez wykonywanie
następujące:
- Skonfiguruj
OutputOptions
za pomocą:prepareRecording()
. - (Opcjonalnie) Włącz nagrywanie dźwięku.
- Użyj
start()
, aby zarejestrowaćVideoRecordEvent
. i rozpocząć nagrywanie filmu.
Recorder
zwraca obiekt Recording
po wywołaniu funkcji start()
.
Aplikacja może użyć tego obiektu Recording
, aby zakończyć
przechwytywania lub wykonywania innych działań, np. wstrzymania lub wznowienia.
Recorder
obsługuje 1 obiekt Recording
naraz. Możesz rozpocząć
nowe nagranie, gdy zadzwonisz do: Recording.stop()
lub
Recording.close()
w poprzednim obiekcie Recording
.
Przyjrzyjmy się tym krokom bardziej szczegółowo. Najpierw aplikacja konfiguruje się
OutputOptions
w przypadku Dyktafonu z systemem Recorder.prepareRecording()
.
Recorder
obsługuje te typy OutputOptions
:
FileDescriptorOutputOptions
za przechwytywanieFileDescriptor
FileOutputOptions
do przechwytywania wFile
.MediaStoreOutputOptions
za przechwytywanieMediaStore
Wszystkie typy OutputOptions
umożliwiają ustawienie maksymalnego rozmiaru pliku
setFileSizeLimit()
Inne opcje zależą od danych wyjściowych
typ, na przykład ParcelFileDescriptor
dla elementu FileDescriptorOutputOptions
.
prepareRecording()
zwraca obiekt PendingRecording
, który jest
obiektu pośredniego, który jest używany do utworzenia
Recording
obiekt. PendingRecording
to klasa przejściowa, która powinna
w większości przypadków jest niewidoczny i rzadko jest zapisywana w pamięci podręcznej aplikacji.
Aplikacje mogą dodatkowo skonfigurować nagrywanie, na przykład:
- Włącz dźwięk za pomocą funkcji
withAudioEnabled()
. - Zarejestruj detektor, aby otrzymywać zdarzenia nagrywania wideo
dzięki
start(Executor, Consumer<VideoRecordEvent>)
. - Zezwól na ciągłe nagrywanie nagrania podczas podłączenia funkcji VideoCapture
jest odsyłany do innej kamery,
PendingRecording.asPersistentRecording()
Aby rozpocząć nagrywanie, zadzwoń pod numer PendingRecording.start()
. AparatX zmienia
PendingRecording
w Recording
, umieszcza żądanie nagrania w kolejce,
i zwraca do aplikacji nowo utworzony obiekt Recording
.
Po rozpoczęciu nagrywania na odpowiednim urządzeniu Aparat X wysyła wiadomość
VideoRecordEvent.EVENT_TYPE_START
.
Z przykładu poniżej dowiesz się, jak nagrać film i dźwięk w
Plik 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 aparatu jest domyślnie wyświetlany w przednim aparacie, które nie są domyślnie powielane. Dzięki CameraX 1.3 możliwe jest teraz powielanie nagrań wideo, dzięki czemu podgląd dopasowania zarejestrowanego filmu.
Dostępne są trzy opcje trybu lustrzany: MIRROR_MODE_OFF, MIRROR_MODE_ON i
MIRROR_MODE_ON_FRONT_ONLY. Aby wyrównać
podglądu z aparatu, Google zaleca korzystanie z MIROR_MODE_ON_FRONT_ONLY, co oznacza, że
które
odbicie lustrzane nie jest włączone w tylnym aparacie, ale jest włączone dla przedniego
aparat fotograficzny. Więcej informacji o trybie MirrorMode:
MirrorMode constants
Ten fragment kodu pokazuje, jak zadzwonić
VideoCapture.Builder.setMirrorMode()
za pomocą: MIRROR_MODE_ON_FRONT_ONLY
. Dla:
więcej informacji: 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);
Sterowanie aktywnym nagraniem
Możesz wstrzymać, wznowić lub zatrzymać trwający Recording
do
w następujący sposób:
pause
aby wstrzymać bieżące aktywne nagranie.resume()
aby wznowić wstrzymane aktywne nagrywanie.stop()
aby zakończyć nagrywanie i usunąć wszystkie powiązane obiekty.mute()
aby wyciszyć bieżące nagranie lub wyłączyć jego wyciszenie.
Pamiętaj, że możesz wywołać stop()
, by zamknąć Recording
niezależnie
czy nagrywanie jest wstrzymane czy aktywne.
Jeśli masz zarejestrowane urządzenie EventListener
u
PendingRecording.start()
, Recording
komunikuje się
za pomocą
VideoRecordEvent
VideoRecordEvent.EVENT_TYPE_STATUS
służy do rejestrowania statystyk takich jak jako bieżącego rozmiaru pliku i zarejestrowanego okresu.- Wynik dotyczący nagrywania:
VideoRecordEvent.EVENT_TYPE_FINALIZE
i zawiera takie informacje, jak identyfikator URI ostatecznego pliku oraz innych błędów.
Gdy aplikacja otrzyma EVENT_TYPE_FINALIZE
, który oznacza pomyślne
oraz sesja nagrywania, można uzyskać dostęp do nagranego filmu
określono w kolumnie OutputOptions
.
Dodatkowe materiały
Więcej informacji o aparacie Aparat X znajdziesz w tych dodatkowych materiałach:
- Pierwsze kroki z programem CameraX
- Oficjalna przykładowa aplikacja CameraX
- Najnowsza lista interfejsu Video Capture API aparatu CameraX
- Informacje o wersji CameraX
- Kod źródłowy aplikacji CameraX