Un sistema di acquisizione generalmente registra stream video e audio, li comprime, li unisce e poi scrive lo stream risultante sul disco.
In CameraX, la soluzione per l'acquisizione di video è il caso d'uso VideoCapture:
VideoCapture.Come mostrato nella Figura 2, l'acquisizione video di CameraX include alcuni componenti architettonici di alto livello:
SurfaceProviderper l'origine video.AudioSourceper la sorgente audio.- Due codificatori per codificare e comprimere video/audio.
- Un muxer multimediale per eseguire il mux dei due stream.
- Un file saver per scrivere il risultato.
L'API VideoCapture astrae il complesso motore di acquisizione e fornisce alle applicazioni un'API molto più semplice e diretta.
Panoramica dell'API VideoCapture
VideoCapture è un caso d'uso di CameraX che funziona bene da solo o se combinato con altri casi d'uso. Le combinazioni specifiche supportate dipendono dalle funzionalità hardware della fotocamera, ma Preview e VideoCapture sono una combinazione di casi d'uso valida su tutti i dispositivi.
L'API VideoCapture è costituita dai seguenti oggetti che comunicano con le applicazioni:
VideoCaptureè la classe di casi d'uso di primo livello.VideoCapturesi associa a unLifecycleOwnercon unCameraSelectore altri UseCase di CameraX. Per ulteriori informazioni su questi concetti e utilizzi, consulta Architettura di CameraX.- Un
Recorderè un'implementazione di VideoOutput strettamente accoppiata aVideoCapture.Recorderviene utilizzato per acquisire video e audio. Un'applicazione crea registrazioni da unRecorder. - Un oggetto
PendingRecordingconfigura una registrazione, fornendo opzioni come l'attivazione dell'audio e l'impostazione di un listener di eventi. Per creare unPendingRecording, devi utilizzare unRecorder. UnPendingRecordingnon registra nulla. - Un
Recordingesegue la registrazione effettiva. Per creare unRecording, devi utilizzare unPendingRecording.
La Figura 3 mostra le relazioni tra questi oggetti:
Legenda:
- Crea un
RecorderconQualitySelector. - Configura
Recordercon uno deiOutputOptions. - Se necessario, attiva l'audio con
withAudioEnabled(). - Chiama
start()con un listenerVideoRecordEventper iniziare la registrazione. - Utilizza
pause()/resume()/stop()sulRecordingper controllare la registrazione. - Rispondi a
VideoRecordEventsall'interno del listener di eventi.
L'elenco dettagliato delle API si trova nel file current.txt all'interno del codice sorgente.
Utilizzo dell'API VideoCapture
Per integrare il caso d'uso VideoCapture di CameraX nella tua app,
procedi nel seguente modo:
- Associa
VideoCapture. - Preparare e configurare la registrazione.
- Avvia e controlla la registrazione del runtime.
Le sezioni seguenti descrivono cosa puoi fare in ogni passaggio per ottenere una sessione di registrazione end-to-end.
Associa VideoCapture
Per associare il caso d'uso VideoCapture, segui questi passaggi:
- Crea un oggetto
Recorder. - Crea l'oggetto
VideoCapture. - Associa a un
Lifecycle.
L'API VideoCapture di CameraX segue il pattern di progettazione del builder. Le applicazioni utilizzano Recorder.Builder per creare un Recorder. Puoi anche configurare la risoluzione video per Recorder tramite un oggetto QualitySelector.
CameraX Recorder supporta i seguenti Qualities predefiniti per le risoluzioni video:
Quality.UHDper le dimensioni dei video 4K Ultra HD (2160p)Quality.QHDper le dimensioni dei video Quad HD (1440p), introdotta in CameraX1.7.0-alpha02Quality.FHDper le dimensioni dei video HD in Full HD (1080p)Quality.HDper le dimensioni dei video HD (720p)Quality.SDper le dimensioni dei video SD (480p)
Tieni presente che CameraX può anche scegliere altre risoluzioni se autorizzato dall'app.
Le dimensioni esatte del video di ogni selezione dipendono dalle funzionalità della videocamera e del codificatore. Per saperne di più, consulta la documentazione relativa a CamcorderProfile.
Le applicazioni possono configurare la risoluzione creando un oggetto QualitySelector.
Puoi creare un QualitySelector utilizzando uno dei seguenti metodi:
Fornisci alcune risoluzioni preferite utilizzando
fromOrderedList()e includi una strategia di riserva da utilizzare nel caso in cui nessuna delle risoluzioni preferite sia supportata.CameraX può decidere la migliore corrispondenza di riserva in base alle funzionalità della fotocamera selezionata. Per maggiori dettagli, consulta
FallbackStrategy specificationdiQualitySelector. Ad esempio, il seguente codice richiede la risoluzione più alta supportata per la registrazione e, se nessuna delle risoluzioni richieste può essere supportata, autorizza CameraX a sceglierne una che sia la più vicina alla risoluzione Quality.SD:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))Esegui prima una query sulle funzionalità della fotocamera e scegli tra le risoluzioni supportate utilizzando
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() } }Tieni presente che la funzionalità restituita da
QualitySelector.getSupportedQualities()funzionerà sicuramente per il caso d'usoVideoCaptureo per la combinazione dei casi d'usoVideoCaptureePreview. Quando viene eseguita l'associazione con il caso d'usoImageCaptureoImageAnalysis, CameraX potrebbe comunque non riuscire ad eseguire l'associazione se la combinazione richiesta non è supportata sulla fotocamera richiesta.
Una volta ottenuto un QualitySelector, l'applicazione può creare un oggetto VideoCapture ed eseguire l'associazione. Tieni presente che questa associazione è la stessa degli altri casi d'uso:
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)
}
Tieni presente che bindToLifecycle() restituisce un oggetto Camera. Consulta questa guida per ulteriori informazioni sul controllo dell'output della videocamera, ad esempio lo zoom e l'esposizione.
Recorder seleziona il formato più adatto per il sistema. Il codec video più comune è H.264 AVC con formato contenitore MPEG-4.
Configura e crea la registrazione
Da un Recorder, l'applicazione può creare oggetti di registrazione per eseguire l'acquisizione di video e audio. Le applicazioni creano registrazioni nel seguente modo:
- Configura
OutputOptionsconprepareRecording(). - (Facoltativo) Attiva la registrazione audio.
- Utilizza
start()per registrare un listenerVideoRecordEvente avviare l'acquisizione video.
Recorder restituisce un oggetto Recording quando chiami la funzione start().
La tua applicazione può utilizzare questo oggetto Recording per completare l'acquisizione o per eseguire altre azioni, ad esempio mettere in pausa o riprendere.
Un Recorder supporta un oggetto Recording alla volta. Puoi avviare una nuova registrazione dopo aver chiamato Recording.stop() o Recording.close() sull'oggetto Recording precedente.
Esaminiamo questi passaggi in modo più dettagliato. Innanzitutto, l'applicazione configura
OutputOptions per un Recorder con Recorder.prepareRecording().
Un Recorder supporta i seguenti tipi di OutputOptions:
FileDescriptorOutputOptionsper l'acquisizione in unFileDescriptor.FileOutputOptionsper l'acquisizione in unFile.MediaStoreOutputOptionsper l'acquisizione in unMediaStore.
Tutti i tipi di OutputOptions consentono di impostare una dimensione massima del file con
setFileSizeLimit(). Altre opzioni sono specifiche per il singolo tipo di output, ad esempio ParcelFileDescriptor per FileDescriptorOutputOptions.
prepareRecording() restituisce un oggetto PendingRecording, ovvero un oggetto intermedio utilizzato per creare l'oggetto Recording corrispondente. PendingRecording è una classe temporanea che dovrebbe essere invisibile nella maggior parte dei casi e viene memorizzata raramente nella cache dall'app.
Le applicazioni possono configurare ulteriormente la registrazione, ad esempio:
- Attiva l'audio con
withAudioEnabled(). - Registra un listener per ricevere gli eventi di registrazione video con
start(Executor, Consumer<VideoRecordEvent>). - Consenti una registrazione continua mentre l'oggetto VideoCapture a cui è collegata viene riassociato a un'altra fotocamera, con
PendingRecording.asPersistentRecording().
Per iniziare a registrare, chiama il numero PendingRecording.start(). CameraX trasforma PendingRecording in un Recording, mette in coda la richiesta di registrazione e restituisce l'oggetto Recording appena creato all'applicazione.
Una volta avviata la registrazione sul dispositivo della fotocamera corrispondente, CameraX invia un evento VideoRecordEvent.EVENT_TYPE_START.
L'esempio seguente mostra come registrare video e audio in un file 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)
Mentre l'anteprima della fotocamera è speculare sulla fotocamera anteriore per impostazione predefinita, i video registrati da VideoCapture non sono speculari per impostazione predefinita. Con CameraX 1.3, ora è possibile specchiare le registrazioni video in modo che l'anteprima della fotocamera anteriore e il video registrato corrispondano.
Esistono tre opzioni MirrorMode: MIRROR_MODE_OFF, MIRROR_MODE_ON e
MIRROR_MODE_ON_FRONT_ONLY. Per l'allineamento all'anteprima della fotocamera, Google consiglia di utilizzare MIROR_MODE_ON_FRONT_ONLY, il che significa che il mirroring non è attivato per la fotocamera posteriore, ma è attivato per la fotocamera anteriore. Per saperne di più su MirrorMode, consulta MirrorMode constants.
Questo snippet di codice mostra come chiamare VideoCapture.Builder.setMirrorMode() utilizzando MIRROR_MODE_ON_FRONT_ONLY. Per saperne di più, consulta 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);
Gamma dinamica (video HDR)
CameraX supporta la registrazione di video High Dynamic Range (HDR) a 10 bit, ad esempio
HLG10, HDR10, HDR10+ o Dolby Vision, utilizzando DynamicRange.
Per utilizzare la registrazione video HDR, segui questi passaggi:
- Esegui una query sulle gamme dinamiche supportate dalla fotocamera utilizzando
VideoCapabilities.getSupportedDynamicRanges(). - (Facoltativo) Se configuri un
QualitySelectorpersonalizzato, controlla quali qualità sono supportate per quel range dinamico utilizzandogetSupportedQualities(DynamicRange). - Configura
VideoCapture.BuilderconsetDynamicRange().
L'esempio seguente attiva la registrazione HDR HLG a 10 bit quando la fotocamera la supporta:
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();
Stabilizzazione video
CameraX supporta la stabilizzazione video per ridurre il tremolio e il jitter della fotocamera durante la registrazione di video.
Per attivare la stabilizzazione video, completa i seguenti passaggi:
- Controlla se il dispositivo della fotocamera supporta la stabilizzazione utilizzando
VideoCapabilities.isStabilizationSupported(). - Attivalo su
VideoCapture.BuilderutilizzandosetVideoStabilizationEnabled(true).
L'esempio seguente attiva la stabilizzazione quando la fotocamera la supporta:
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();
Controlla una registrazione attiva
Puoi mettere in pausa, riprendere e interrompere un Recording in corso utilizzando i seguenti metodi:
pauseper mettere in pausa la registrazione attiva corrente.resume()per riprendere una registrazione attiva in pausa.stop()per terminare la registrazione e svuotare tutti gli oggetti di registrazione associati.mute()per disattivare o riattivare l'audio della registrazione corrente.
Tieni presente che puoi chiamare stop() per terminare una Recording indipendentemente dal fatto che la registrazione sia in pausa o attiva.
Se hai registrato un EventListener con
PendingRecording.start(), Recording comunica
utilizzando un
VideoRecordEvent.
VideoRecordEvent.EVENT_TYPE_STATUSviene utilizzato per registrare statistiche come le dimensioni attuali del file e l'intervallo di tempo registrato.VideoRecordEvent.EVENT_TYPE_FINALIZEviene utilizzato per il risultato della registrazione e include informazioni come l'URI del file finale, insieme a eventuali errori correlati.
Una volta che l'app riceve un EVENT_TYPE_FINALIZE che indica una sessione di registrazione riuscita, puoi accedere al video acquisito dalla posizione specificata in OutputOptions.
Ampiezza e stato dell'audio in tempo reale
Durante la registrazione, gli eventi VideoRecordEvent.Status forniscono statistiche audio in tempo reale tramite AudioStats:
AudioStats.getAudioAmplitude()restituisce l'ampiezza di picco audio corrente, compresa tra0.0e1.0. Puoi utilizzare questo valore per gestire i misuratori della UI o i visualizzatori delle forme d'onda audio.AudioStats.getAudioState()indica lo stato attuale dello stream audio, ad esempioAUDIO_STATE_ACTIVE,AUDIO_STATE_MUTEDoAUDIO_STATE_SOURCE_SILENCED.
L'esempio seguente legge l'ampiezza dell'audio da un evento di stato:
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); } }
Video ad alta velocità e in slow motion
CameraX supporta la registrazione di video ad alta velocità, ad esempio a 120, 240 o 480 f/s, il che consente due casi d'uso distinti:
- Video con frequenza fotogrammi elevata (slow motion gestito dal player): CameraX acquisisce e salva i fotogrammi con una frequenza fotogrammi elevata (ad esempio 120 fps). Il video player controlla la velocità di riproduzione, consentendo agli utenti di passare dalla velocità normale allo slow motion o di eseguire un'analisi fotogramma per fotogramma.
- Video in slow motion pronto per la riproduzione: CameraX elabora lo stream ad alta velocità e genera un file video standard a 30 f/s con timestamp dei frame modificati. L'effetto slow motion è "incorporato", quindi il video viene riprodotto automaticamente in slow motion in qualsiasi video player standard senza supporto speciale. Ad esempio, un'acquisizione a 120 f/s riprodotta a 30 f/s produce un video in slow motion 1/4x.
Verifica le funzionalità ad alta velocità
L'acquisizione di video ad alta velocità richiede il supporto hardware e le definizioni di CamcorderProfile corrispondenti dei produttori di dispositivi, come CamcorderProfile.QUALITY_HIGH_SPEED_1080P o QUALITY_HIGH_SPEED_720P.
Prima di configurare la registrazione ad alta velocità, esegui una query sulle funzionalità ad alta velocità utilizzando
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);
Configura HighSpeedVideoSessionConfig
Per utilizzare l'acquisizione ad alta velocità, combina i casi d'uso VideoCapture e Preview in un HighSpeedVideoSessionConfig. Per configurare la sessione, completa i seguenti passaggi:
- Crea un caso d'uso
VideoCapturee un caso d'usoPreview. - Inizializza
HighSpeedVideoSessionConfig.Buildercon il caso d'usoVideoCapturee collegaPreview. - Esegui una query sugli intervalli di frequenza fotogrammi supportati utilizzando
CameraInfo.getSupportedFrameRateRanges(SessionConfig)e imposta l'intervallo selezionato. - Scegli tra un video con frequenza fotogrammi elevata o un video in slow motion pronto per la riproduzione:
- Per creare un video con frequenza fotogrammi elevata, lascia
setSlowMotionEnabled(false)(predefinito). - Per creare un video in slow motion pronto per la riproduzione, chiama
setSlowMotionEnabled(true).
- Per creare un video con frequenza fotogrammi elevata, lascia
- Associa la configurazione della sessione utilizzando
cameraProvider.bindToLifecycle().
L'esempio seguente configura e associa una sessione in slow motion pronta per la riproduzione:
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 );
Puoi anche utilizzare il DSL Kotlin, introdotto in CameraX 1.7.0-alpha02, per configurare le sessioni ad alta velocità in modo conciso:
val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
this.preview = preview
isSlowMotionEnabled = true
frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
sessionConfig
)
Registra video ad alta velocità o in slow motion
Dopo aver associato HighSpeedVideoSessionConfig, avvia la registrazione utilizzando
VideoCapture nello stesso modo delle registrazioni video standard:
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()); } } });
Risorse aggiuntive
Per scoprire di più su CameraX, consulta le seguenti risorse aggiuntive:
- Codelab Guida introduttiva a CameraX
- App di esempio ufficiale di CameraX
- Elenco più recente delle API CameraX Video Capture
- Note di rilascio di CameraX
- Codice sorgente di CameraX
- High-Speed Capture and Slow-Motion Video with CameraX 1.5