Architettura di acquisizione video con CameraX

Un sistema di acquisizione generalmente registra stream video e audio, li comprime, li unisce e poi scrive lo stream risultante sul disco.

diagramma concettuale per un sistema di acquisizione video e audio
Figura 1. Diagramma concettuale per un sistema di acquisizione video e audio.

In CameraX, la soluzione per l'acquisizione di video è il caso d'uso VideoCapture:

diagramma concettuale che mostra come CameraX gestisce il caso d'uso di acquisizione video
Figura 2. Diagramma concettuale che mostra in che modo CameraX gestisce il caso d'uso VideoCapture.

Come mostrato nella Figura 2, l'acquisizione video di CameraX include alcuni componenti architettonici di alto livello:

  • SurfaceProvider per l'origine video.
  • AudioSource per 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. VideoCapture si associa a un LifecycleOwner con un CameraSelector e altri UseCase di CameraX. Per ulteriori informazioni su questi concetti e utilizzi, consulta Architettura di CameraX.
  • Un Recorder è un'implementazione di VideoOutput strettamente accoppiata a VideoCapture. Recorder viene utilizzato per acquisire video e audio. Un'applicazione crea registrazioni da un Recorder.
  • Un oggetto PendingRecording configura una registrazione, fornendo opzioni come l'attivazione dell'audio e l'impostazione di un listener di eventi. Per creare un PendingRecording, devi utilizzare un Recorder. Un PendingRecording non registra nulla.
  • Un Recording esegue la registrazione effettiva. Per creare un Recording, devi utilizzare un PendingRecording.

La Figura 3 mostra le relazioni tra questi oggetti:

diagramma che mostra le interazioni che si verificano in un caso d'uso di acquisizione video
Figura 3. Diagramma che mostra le interazioni che si verificano in un caso d'uso di VideoCapture.

Legenda:

  1. Crea un Recorder con QualitySelector.
  2. Configura Recorder con uno dei OutputOptions.
  3. Se necessario, attiva l'audio con withAudioEnabled().
  4. Chiama start() con un listener VideoRecordEvent per iniziare la registrazione.
  5. Utilizza pause()/resume()/stop() sul Recording per controllare la registrazione.
  6. Rispondi a VideoRecordEvents all'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:

  1. Associa VideoCapture.
  2. Preparare e configurare la registrazione.
  3. 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:

  1. Crea un oggetto Recorder.
  2. Crea l'oggetto VideoCapture.
  3. 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.UHD per le dimensioni dei video 4K Ultra HD (2160p)
  • Quality.QHD per le dimensioni dei video Quad HD (1440p), introdotta in CameraX 1.7.0-alpha02
  • Quality.FHD per le dimensioni dei video HD in Full HD (1080p)
  • Quality.HD per le dimensioni dei video HD (720p)
  • Quality.SD per 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 specification di QualitySelector. 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'uso VideoCapture o per la combinazione dei casi d'uso VideoCapture e Preview. Quando viene eseguita l'associazione con il caso d'uso ImageCapture o ImageAnalysis, 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:

  1. Configura OutputOptions con prepareRecording().
  2. (Facoltativo) Attiva la registrazione audio.
  3. Utilizza start() per registrare un listener VideoRecordEvent e 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:

  • FileDescriptorOutputOptions per l'acquisizione in un FileDescriptor.
  • FileOutputOptions per l'acquisizione in un File.
  • MediaStoreOutputOptions per l'acquisizione in un MediaStore.

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:

  1. Esegui una query sulle gamme dinamiche supportate dalla fotocamera utilizzando VideoCapabilities.getSupportedDynamicRanges().
  2. (Facoltativo) Se configuri un QualitySelector personalizzato, controlla quali qualità sono supportate per quel range dinamico utilizzando getSupportedQualities(DynamicRange).
  3. Configura VideoCapture.Builder con setDynamicRange().

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:

  1. Controlla se il dispositivo della fotocamera supporta la stabilizzazione utilizzando VideoCapabilities.isStabilizationSupported().
  2. Attivalo su VideoCapture.Builder utilizzando setVideoStabilizationEnabled(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:

  • pause per 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_STATUS viene utilizzato per registrare statistiche come le dimensioni attuali del file e l'intervallo di tempo registrato.
  • VideoRecordEvent.EVENT_TYPE_FINALIZE viene 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 tra 0.0 e 1.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 esempio AUDIO_STATE_ACTIVE, AUDIO_STATE_MUTED o AUDIO_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:

  1. Crea un caso d'uso VideoCapture e un caso d'uso Preview.
  2. Inizializza HighSpeedVideoSessionConfig.Builder con il caso d'uso VideoCapture e collega Preview.
  3. Esegui una query sugli intervalli di frequenza fotogrammi supportati utilizzando CameraInfo.getSupportedFrameRateRanges(SessionConfig) e imposta l'intervallo selezionato.
  4. 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).
  5. 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: