Architecture de capture vidéo de CameraX

Un système de capture enregistre généralement des flux vidéo et audio, les compresse, multiplexe les deux flux, puis écrit le flux obtenu sur le disque.

Schéma conceptuel d'un système de capture vidéo et audio
Figure 1. Schéma conceptuel d'un système de capture vidéo et audio

Dans CameraX, la solution de capture vidéo est le cas d'utilisation VideoCapture :

Schéma conceptuel montrant comment CameraX gère la capture vidéo.
Figure 2. Schéma conceptuel montrant comment CameraX gère le cas d'utilisation VideoCapture.

Comme le montre la figure 2, la capture vidéo de CameraX inclut quelques composants architecturaux de haut niveau :

  • SurfaceProvider pour la source vidéo.
  • AudioSource pour la source audio.
  • Deux encodeurs permettent d'encoder et de compresser la vidéo et l'audio.
  • Un multiplexeur multimédia pour combiner les deux flux.
  • Un saver de fichier pour écrire le résultat.

L'API VideoCapture fait abstraction du moteur de capture complexe et fournit aux applications une API bien plus simple et directe.

Présentation de l'API VideoCapture

VideoCapture est un cas d'utilisation de CameraX qui fonctionne bien seul ou lorsqu'il est combiné à d'autres cas d'utilisation. Les combinaisons spécifiques compatibles dépendent des capacités matérielles de l'appareil photo, mais Preview et VideoCapture forment une combinaison valide pour tous les appareils.

L'API VideoCapture comprend les objets suivants qui communiquent avec les applications :

  • VideoCapture est la classe du cas d'utilisation de premier niveau. VideoCapture se lie à un LifecycleOwner avec un CameraSelector et à d'autres cas d'utilisation de CameraX. Pour en savoir plus sur ces concepts et ces utilisations, consultez la page Architecture de CameraX.
  • Un Recorder est une implémentation de VideoOutput étroitement couplée à VideoCapture. Recorder permet de capture du contenu vidéo et audio. Une application crée des enregistrements à partir d'un Recorder.
  • Un PendingRecording configure un enregistrement, ce qui permet d'activer l'audio et de définir un écouteur d'événements. Vous devez utiliser un Recorder pour créer un PendingRecording. Un PendingRecording n'enregistre rien.
  • Un Recording effectue l'enregistrement réel. Vous devez utiliser un PendingRecording pour créer un Recording.

La figure 3 illustre les relations entre ces objets :

Diagramme illustrant les interactions qui se produisent dans un cas d'utilisation de capture vidéo
Figure 3. Schéma illustrant les interactions dans un cas d'utilisation de VideoCapture.

Légende :

  1. Créez un Recorder avec QualitySelector.
  2. Configurez le Recorder avec l'une des OutputOptions.
  3. Si nécessaire, activez l'audio avec withAudioEnabled().
  4. Appelez start() avec un écouteur VideoRecordEvent pour commencer l'enregistrement.
  5. Utilisez pause()/resume()/stop() sur le Recording pour contrôler l'enregistrement.
  6. Répondez à VideoRecordEvents dans votre écouteur d'événements.

La liste détaillée des API se trouve dans le fichier current.txt à l'intérieur du code source.

Utiliser l'API VideoCapture

Pour intégrer le cas d'utilisation VideoCapture de CameraX dans votre application, procédez comme suit :

  1. Liez VideoCapture.
  2. Préparez et configurez l'enregistrement.
  3. Démarrez et contrôlez l'enregistrement de l'environnement d'exécution.

Les sections suivantes décrivent ce que vous pouvez faire à chaque étape pour obtenir une session d'enregistrement de bout en bout.

Lier VideoCapture

Pour lier le cas d'utilisation VideoCapture, procédez comme suit :

  1. Créez un objet Recorder.
  2. Créez un objet VideoCapture.
  3. Liez-les à un Lifecycle.

L'API CameraX VideoCapture respecte le schéma de conception du compilateur. Les applications utilisent Recorder.Builder pour créer un Recorder. Vous pouvez également configurer la résolution vidéo de Recorder via un objet QualitySelector.

CameraX Recorder est compatible avec les Qualities prédéfinies pour les résolutions vidéo :

  • Quality.UHD pour une vidéo 4K Ultra HD (2 160 p)
  • Quality.QHD pour une vidéo en Quad HD (1 440 p), introduite dans CameraX 1.7.0-alpha02
  • Quality.FHD pour une vidéo en Full HD (1 080 p)
  • Quality.HD pour une vidéo HD (720 p)
  • Quality.SD pour une vidéo SD (480 p)

Sachez que CameraX peut également choisir d'autres résolutions si l'application le permet.

La taille exacte de la vidéo de chaque sélection dépend des capacités de l'appareil photo et de l'encodeur. Pour en savoir plus, consultez la documentation pour CamcorderProfile.

Les applications peuvent configurer la résolution en créant un QualitySelector. Vous pouvez créer un QualitySelector à l'aide de l'une des méthodes suivantes :

  • Indiquez quelques résolutions privilégiées à l'aide de fromOrderedList() et incluez une stratégie de remplacement à utiliser si aucune des résolutions souhaitées n'est compatible.

    CameraX peut choisir la meilleure correspondance de remplacement en fonction de la capacité de l'appareil photo sélectionné. Pour en savoir plus, consultez la FallbackStrategy specification de QualitySelector. Par exemple, le code suivant demande la résolution la plus élevée pour l'enregistrement. Si aucune des résolutions de requête ne peut être acceptée, autorisez CameraX à en choisir une résolution qui se rapproche le plus de la résolution Quality.SD :

    val qualitySelector = QualitySelector.fromOrderedList(
             listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD),
             FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
    
  • Commencez par interroger les capacités de l'appareil photo, puis choisissez l'une des résolutions compatibles à l'aide de 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()
        }
    }
    
    

    Notez que la capacité renvoyée par QualitySelector.getSupportedQualities() garantit le fonctionnement avec le cas d'utilisation de VideoCapture ou pour la combinaison des cas d'utilisation VideoCapture et Preview. Lors de la liaison avec le cas d'utilisation ImageCapture ou ImageAnalysis, CameraX peut tout de même échouer si la combinaison requise n'est pas compatible avec l'appareil photo demandé.

Une fois que vous disposez d'un QualitySelector, l'application peut créer un objet VideoCapture et effectuer la liaison. Notez que cette liaison est identique à celle utilisée pour d'autres cas d'utilisation :

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)
}

Notez que bindToLifecycle() renvoie un objet Camera. Pour en savoir plus sur le contrôle de la sortie de l'appareil photo, comme le zoom et l'exposition, consultez ce guide.

Le Recorder sélectionne le format le plus adapté au système. Le codec vidéo le plus courant est H.264 AVC au format de conteneur MPEG-4.

Configurer et créer un enregistrement

À partir d'un Recorder, l'application peut créer des objets d'enregistrement pour effectuer la capture vidéo et audio. Les applications créent des enregistrements en procédant comme suit :

  1. Configurez OutputOptions avec le prepareRecording().
  2. (Facultatif) Activez l'enregistrement audio.
  3. Utilisez start() pour enregistrer un écouteur VideoRecordEvent et commencer à enregistrer des vidéos.

Le Recorder renvoie un objet Recording lorsque vous appelez la fonction start(). Votre application peut utiliser cet objet Recording pour terminer la capture ou effectuer d'autres actions, telles que la mise en pause ou la reprise.

Un objet Recorder accepte un seul objet Recording à la fois. Vous pouvez démarrer un nouvel enregistrement une fois que vous avez appelé Recording.stop() ou Recording.close() sur l'objet Recording précédent.

Examinons ces étapes plus en détail. Tout d'abord, l'application configure les OutputOptions pour un enregistreur avec Recorder.prepareRecording(). Un Recorder est compatible avec les types de OutputOptions suivants :

  • FileDescriptorOutputOptions pour la capture dans un FileDescriptor.
  • FileOutputOptions pour la capture dans un File.
  • MediaStoreOutputOptions pour la capture dans un MediaStore.

Tous les types OutputOptions vous permettent de définir une taille de fichier maximale avec setFileSizeLimit(). D'autres options sont propres au type de sortie individuel, par exemple ParcelFileDescriptor pour les FileDescriptorOutputOptions.

prepareRecording() renvoie un objet PendingRecording, qui est un objet intermédiaire utilisé pour créer l'objet Recording correspondant. PendingRecording est une classe temporaire qui doit être invisible dans la plupart des cas et qui est rarement mise en cache par l'application.

Les applications peuvent également configurer l'enregistrement, par exemple :

  • Activez l'audio avec withAudioEnabled().
  • Enregistrez un écouteur pour recevoir des événements d'enregistrement vidéo avec start(Executor, Consumer<VideoRecordEvent>).
  • Permet à un enregistrement d'enregistrer en continu alors que la VideoCapture à laquelle il est associé est reliée à une autre caméra, avec PendingRecording.asPersistentRecording().

Pour commencer l'enregistrement, appelez PendingRecording.start(). CameraX transforme le PendingRecording en un Recording, met la requête en file d'attente et renvoie l'objet Recording nouvellement créé à l'application. Une fois que l'enregistrement a commencé sur l'appareil photo correspondant, CameraX envoie un événement VideoRecordEvent.EVENT_TYPE_START.

L'exemple suivant montre comment enregistrer du contenu vidéo et audio dans un fichier 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)

Alors que par défaut, l'aperçu de la caméra avant est mis en miroir, ce n'est pas le cas des vidéos enregistrées par VideoCapture. Avec CameraX 1.3, il est maintenant possible de mettre en miroir les enregistrements vidéo afin que l'aperçu de la caméra avant et la vidéo enregistrée correspondent.

Trois options existent pour le mode MirrorMode : MIRROR_MODE_OFF, MIRROR_MODE_ON et MIRROR_MODE_ON_FRONT_ONLY. Pour aligner l'aperçu de la caméra, Google recommande d'utiliser MIROR_MODE_ON_FRONT_ONLY, ce qui signifie que la mise en miroir n'est pas activée pour la caméra arrière, mais l'est pour la caméra avant. Pour en savoir plus sur le mode MirrorMode, consultez MirrorMode constants.

Cet extrait de code vous montre comment appeler VideoCapture.Builder.setMirrorMode() à l'aide de MIRROR_MODE_ON_FRONT_ONLY. Pour en savoir plus, consultez 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);

Plage dynamique (vidéo HDR)

CameraX est compatible avec l'enregistrement vidéo HDR (High Dynamic Range) 10 bits, comme HLG10, HDR10, HDR10+ ou Dolby Vision, à l'aide de DynamicRange.

Pour utiliser l'enregistrement vidéo HDR, procédez comme suit :

  1. Interrogez les plages dynamiques compatibles avec la caméra à l'aide de VideoCapabilities.getSupportedDynamicRanges().
  2. Facultatif : Si vous configurez un QualitySelector personnalisé, vérifiez les qualités compatibles avec cette plage dynamique à l'aide de getSupportedQualities(DynamicRange).
  3. Configurez VideoCapture.Builder avec setDynamicRange().

L'exemple suivant active l'enregistrement HDR HLG 10 bits lorsque l'appareil photo le permet :

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();

Stabilisation vidéo

CameraX est compatible avec la stabilisation vidéo pour réduire les tremblements et les saccades lors de l'enregistrement vidéo.

Pour activer la stabilisation vidéo, procédez comme suit :

  1. Vérifiez si l'appareil photo est compatible avec la stabilisation à l'aide de VideoCapabilities.isStabilizationSupported().
  2. Activez-le sur VideoCapture.Builder à l'aide de setVideoStabilizationEnabled(true).

L'exemple suivant active la stabilisation lorsque la caméra la prend en charge :

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();

Contrôler un enregistrement actif

Vous pouvez suspendre, reprendre et arrêter un Recording en cours à l'aide des méthodes suivantes :

  • pause pour suspendre l'enregistrement actif en cours.
  • resume() pour reprendre un enregistrement actif mis en pause
  • stop() pour terminer l'enregistrement et vider tous les objets d'enregistrement associés.
  • mute() pour activer ou désactiver le son de l'enregistrement actuel.

Notez que vous pouvez appeler stop() pour arrêter un Recording, que l'enregistrement soit mis en pause ou actif.

Si vous avez enregistré un EventListener avec PendingRecording.start(), Recording communique à l'aide d'un VideoRecordEvent.

  • VideoRecordEvent.EVENT_TYPE_STATUS permet d'enregistrer des statistiques telles que la taille de fichier actuelle et la période enregistrée.
  • VideoRecordEvent.EVENT_TYPE_FINALIZE est utilisé pour le résultat de l'enregistrement et inclut des informations telles que l'URI du fichier final ainsi que les erreurs associées.

Une fois que votre application reçoit un EVENT_TYPE_FINALIZE indiquant une session d'enregistrement réussie, vous pouvez accéder à la vidéo capturée à partir de l'emplacement spécifié dans OutputOptions.

Amplitude et état audio en temps réel

Pendant l'enregistrement, les événements VideoRecordEvent.Status fournissent des statistiques audio en temps réel via AudioStats :

  • AudioStats.getAudioAmplitude() renvoie l'amplitude maximale actuelle de l'audio, comprise entre 0.0 et 1.0. Vous pouvez utiliser cette valeur pour piloter des indicateurs d'interface utilisateur ou des visualiseurs de formes d'onde audio.
  • AudioStats.getAudioState() indique l'état actuel du flux audio, par exemple AUDIO_STATE_ACTIVE, AUDIO_STATE_MUTED ou AUDIO_STATE_SOURCE_SILENCED.

L'exemple suivant lit l'amplitude audio à partir d'un événement d'état :

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);
    }
}

Vidéos à haute vitesse et au ralenti

CameraX est compatible avec l'enregistrement vidéo à grande vitesse, par exemple à 120, 240 ou 480 FPS, ce qui permet deux cas d'utilisation distincts :

  • Vidéo à fréquence d'images élevée (ralenti géré par le lecteur) : CameraX capture et enregistre les images à une fréquence d'images élevée (par exemple, 120 FPS). Le lecteur vidéo contrôle la vitesse de lecture, ce qui permet aux utilisateurs de basculer entre la vitesse normale et le ralenti, ou d'effectuer une analyse image par image.
  • Vidéo au ralenti prête à être lue : CameraX traite le flux à grande vitesse et génère un fichier vidéo standard de 30 FPS avec des codes temporels d'images ajustés. L'effet de ralenti est "intégré", de sorte que la vidéo est lue automatiquement au ralenti dans n'importe quel lecteur vidéo standard, sans qu'il soit nécessaire d'utiliser un lecteur vidéo spécial. Par exemple, une capture à 120 fps lue à 30 fps produit une vidéo au ralenti 1/4x.

Vérifier les capacités haut débit

La capture vidéo à grande vitesse nécessite une compatibilité matérielle et les définitions CamcorderProfile correspondantes des fabricants d'appareils, telles que CamcorderProfile.QUALITY_HIGH_SPEED_1080P ou QUALITY_HIGH_SPEED_720P.

Avant de configurer l'enregistrement à grande vitesse, interrogez les fonctionnalités à grande vitesse à l'aide de 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);

Configurer HighSpeedVideoSessionConfig

Pour utiliser la capture à grande vitesse, combinez vos cas d'utilisation VideoCapture et Preview dans un HighSpeedVideoSessionConfig. Pour configurer la session, procédez comme suit :

  1. Créez un cas d'utilisation VideoCapture et un cas d'utilisation Preview.
  2. Initialisez HighSpeedVideoSessionConfig.Builder avec le cas d'utilisation VideoCapture et associez Preview.
  3. Interrogez les plages de fréquences d'images compatibles à l'aide de CameraInfo.getSupportedFrameRateRanges(SessionConfig) et définissez la plage sélectionnée.
  4. Choisissez entre une vidéo à fréquence d'images élevée ou une vidéo au ralenti prête à être lue :
    • Pour créer une vidéo à fréquence d'images élevée, laissez setSlowMotionEnabled(false) (par défaut).
    • Pour créer une vidéo au ralenti prête à être lue, appelez setSlowMotionEnabled(true).
  5. Liez la configuration de session à l'aide de cameraProvider.bindToLifecycle().

L'exemple suivant configure et lie une session au ralenti prête à être lue :

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
);

Vous pouvez également utiliser le DSL Kotlin, introduit dans CameraX 1.7.0-alpha02, pour configurer des sessions à grande vitesse de manière concise :

val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
    this.preview = preview
    isSlowMotionEnabled = true
    frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    sessionConfig
)

Enregistrer une vidéo en accéléré ou au ralenti

Après avoir lié le HighSpeedVideoSessionConfig, commencez l'enregistrement à l'aide de VideoCapture, de la même manière que pour les enregistrements vidéo standards :

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());
            }
        }
    });

Ressources supplémentaires

Pour en savoir plus sur CameraX, consultez les ressources supplémentaires suivantes :